【Java】Java socket通讯使用read,readline函数的阻塞问题

Socket通讯是Java网络编程中比较基础的部分,其原理其实就是源ip,源端口和目的ip,目的端口组成的套接字通讯。其底层还设及到了TCP协议的通讯。编程

Java中的Socket通讯能够经过客户端的Socket与服务端的ServerSocket通讯,同时利用IO流传递数据,也就是说Socket通讯是面向流的使用的是BIO,并不一样于后来的NIO通讯面向缓冲。Socket通讯中使用的IO流的read,readline等函数都是阻塞的,这就致使了在通讯过程当中,双方不能肯定什么时侯是流的结束,针对这种能够经过约定结束符的方式进行结束,也能够约定一次传输的字节流的长度。下面经过代码进行说明网络

客户端

创建客户端线程,在run方法中不断对服务端进行发送消息,模拟多个客户端的通讯,经过写入换行符,代表此次通讯的结束。socket

 1 class Client implements Runnable {
 2 
 3     private byte[] targetIp;
 4     private int port;
 5 
 6     Client(byte[] ip, int port) {
 7         this.targetIp = ip;
 8         this.port = port;
 9     }
10 
11     @Override
12     public void run() {
13         try {
14             InetAddress inetAddress = InetAddress.getByAddress(targetIp);
15             Socket socket = new Socket(inetAddress, port);
16             System.out.println("client");
17             BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
18             BufferedWriter socketOutput = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
19 
20             int i = 0;
21             String NAME = "Client";
22             while (true) {
23                 socketOutput.write("This msg from " + NAME + " msg id is " + i);
24                 socketOutput.write("\n");//约定结束符表示流的结束
25                 i++;
26                 socketOutput.flush();
27                 System.out.println("here");
28                 String str = null;
29                 if (!(str = socketInput.readLine()).equals("\n")) {
30                     System.out.println(str);
31                 }
32 
33             }
34 
35             /*socket.shutdownInput();
36             socket.shutdownOutput();*/
37         } catch (IOException e) {
38             e.printStackTrace();
39         }
40 
41     }
42 }

服务端

服务端经过accept接受客户端的链接,这个操做是阻塞的,直到有客户端的链接才能进行下一步。ide

 1 class Server implements Runnable {
 2 
 3     private int port;
 4 
 5     Server(int port) {
 6         this.port = port;
 7     }
 8     @Override
 9     public void run() {
10         try {
11             ServerSocket serverSocket = new ServerSocket(port);
12 
13             InetAddress inetAddress = serverSocket.getInetAddress();
14             System.out.println("server" + inetAddress.getHostAddress());
15             Socket socket = serverSocket.accept();
16             BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
17             BufferedWriter socketOutput = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
18 
19             int i = 0;
20             while (true) {
21                 String str = null;
22                 if (!(str = socketInput.readLine()).equals("\n")) System.out.println(str);
23                 System.out.println("server");
24 
25                 String NAME = "Server";
26                 socketOutput.write("This msg from " + NAME + " msg num is " + i + " reply to " + str);
27                 socketOutput.write("\n");
28                 i++;
29                 socketOutput.flush();
30             }
31 
32 //            socket.shutdownInput();
33 //            socket.shutdownOutput();
34         } catch (IOException e) {
35             e.printStackTrace();
36         }
37 
38     }
39 }

测试

 1 public class SocketTest {
 2     public static void main(String[] args) {
 3         byte[] ip = {127, 0, 0, 1};
 4         int port = 27149;
 5         Thread server = new Thread(new Server(port), "server");
 6         server.start();
 7         Thread client = new Thread(new Client(new byte[]{0,0,0,0}, 27149));
 8         client.start();
 9     }
10 }

结果

服务端针对客户端的每条信息都可以进行读取并返回消息给客户端,可是若是注释掉写入换行符,并判断读取是不是换行符的代码,就没法读取到流的结束。函数

相关文章
相关标签/搜索