使用Socket编写Client-Server通信总结

    xiaoxiao2021-03-29  35

    Socket通信是基于TCP/IP协议的一种进程间通信方式, 通过指定IP地址和端口号进行客户端与服务器的连接完成通信,使用Socket编程时的步骤如下: 服务器端: 第1步.实例化监听套接字,并指定端口号: //一台服务器默认端口号有256*256,其中1~1023是公认端口号,1024~65535可以自定义作用; ServerSocket server = new ServerSocket(9999); 第2步.调用accept()等待客户端连接,如果没有客户端进行连接,此方法一直处于阻塞状态,直到有客户端连接,接触阻塞并返回套接字: Socket socket = server.accept(); 第3步. 使用流进根据套接字得到输入输出流进行通信: InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); 第4步.关闭套接字、流资源: socket.close; is.close(); os.close(); 客户端: 第1步.实例化套接字,并指定服务器地址和端口: Socket socket = new Socket("127.0.0.1",9999); 第2步.使用流进根据套接字得到输入输出流进行通信: InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); 第3步. 关闭套接字、流资源: socket.close; is.close(); os.close(); 其中难点就在使用流进行传输,当我使用缓冲流BufferedReader和BufferedWriter时,代码如下: //客户端中向服务器写入数据的流 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //服务器中读取客户端数据的流 reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); while((content=reader.readLine())!=null){ if(content.equals("over")){ System.out.println(hostName+"已下线!"); break; } StringBuffer buffer = new StringBuffer(content); writer.println(buffer.reverse().toString()); System.out.println(hostName+"说:"+content); } 此时readLine()一直处于阻塞状态,读取不到数据,这是因为readLine()用于读取一行数据,通过换行符来判断,在一般操作中通过控制台输入数据,是可以读取到的,但是在Socket中没有提供换行符,因此一直处于阻塞状态。 解决办法: 第一种:通过BufferedWriter的newLine()写入一个分隔符,之后采用flush()刷新: writer.write(String); writer.newLine(); writer.flush(); 第二种:采用打印流PrintWriter代替BufferedWriter,不过要注意,PrinterWriter刷新缓冲区的操作,如下: //实例化PrintWriter实例,true表示启用了自动刷新,但只有调用println()、format()、printf()时才能自动刷新 writer = new PrintWriter(socket.getOutputStream(),true); writer.println(String); 下面是用Socket编程实现多人聊天代码: 客户端: import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Socket socket =null; try { //1.实例化监听套接字 ServerSocket server = new ServerSocket(1994); /** * 根据监听套接字获取套接字,当每有一个客户端连接服务器时,开启一个子线程进行通讯, * 将通讯交给子线程完成 */ while(true){ socket = server.accept(); new Thread(new Service(socket)).start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 子线程中处理通讯的类: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class Service implements Runnable{ private Socket socket; private String hostName; private BufferedReader reader; private PrintWriter writer; public Service(Socket socket) { super(); this.socket = socket; //通过socket获取客户端主机名 hostName = socket.getInetAddress().getHostName(); try { //读取客户端消息 reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); //给客户端发送消息 writer = new PrintWriter(socket.getOutputStream(),true); System.out.println(hostName+"已上线!"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { // TODO Auto-generated method stub String content = null; try { while((content=reader.readLine())!=null){ if(content.equals("over")){ System.out.println(hostName+"已下线!"); break; } StringBuffer buffer = new StringBuffer(content); writer.println(buffer.reverse().toString()); System.out.println(hostName+"说:"+content); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(reader != null){ reader.close(); reader = null; } if(socket != null){ socket.close(); socket = null; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } 客户端: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class Client { /** * @param args */ private static BufferedWriter writer; private static BufferedReader reader_keyboard,readr_fromServer; public static void main(String[] args) { // TODO Auto-generated method stub Socket socket = null; try { //1.实例化套接字,并指定主机地址和端口号 socket = new Socket(InetAddress.getLocalHost(), 1994); //向服务器写入数据的流 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //接收从键盘输入的数据 reader_keyboard = new BufferedReader(new InputStreamReader(System.in)); readr_fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); String content = null; String contentFromServer = null; do{ System.out.println("请输入信息:"); content = reader_keyboard.readLine(); if(content.equals("over")){ break; } writer.write(content); writer.newLine(); writer.flush(); contentFromServer = readr_fromServer.readLine(); if(contentFromServer!=null){ System.out.println("服务器:"+contentFromServer); } }while(true); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(reader_keyboard != null){ reader_keyboard.close(); reader_keyboard = null; } if(socket != null){ socket.close(); socket = null; } if(writer != null){ writer.close(); writer = null; } } catch (IOException e) { // TODO: handle exception } } } }
    转载请注明原文地址: https://ju.6miu.com/read-664899.html

    最新回复(0)