最初的需求:
············代码片段············
//1、创建一个服务端Socket,即ServerSocket对象,指定绑定的端口,并侦听该端口
ServerSocket serverSocket = new ServerSocket(6666);
//2、调用accept()方法开始侦听客户端请求,创建Socket,等待客户端的连接
System.out.println("===================服务器即将启动,等待客户端的连接===============");
Socket socket = serverSocket.accept();
System.out.println(new Date());
System.out.println("=========连接成功==========");
············代码片段············
( 自己编写的JAVA程序,作为服务器端,接收客户端发来的消息,并且实时输出至控制台。)
遇到的第一个问题:
我先发送了第一条消息MESSAGE1,客户端已经发送成功,但是服务器端并没有将接收到的字符串打印出来,于是我又接着发了两条:MESSAGE2 MESSAGE3并且断开了连接。
String text = null;
String data = null;
while(null != (text = (data = br.readLine()))) {
System.out.println(new Date());
System.out.println("我是服务器端,客户端说:"+ data);
}
当时翻来覆去也没有想明白这段代码有什么问题,还自己写了一个客户端来进行检查,结果在自己写的客户端上消息都是实时显示的。但是出于需求的原因,客户端只能用这个软件来模拟,不能自己编写,于是便继续寻找解决方案。
当时以为是缓冲区拥堵,于是改写了代码,结果引发了第二个问题。
遇到的第二个问题:
char[] b = new char[1024];
int len = 0;
while((len = br.read(b)) != -1) {
System.out.println(new Date());
System.out.println("我是服务器端,客户端说:"+new String(b));
}
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/1d66d69ac1e63f8354e5ba35a3677364.png)
虽然消息能够实时显示了,但是出现了更严重的问题:
我分别发送了三次消息
MESSAGE1
HELLO
HI
可以看到,这里产生了消息的黏连。
后来经过N久的思考,想出了这个问题的原因:
由于服务端进行socket消息的处理,客户端负责消息的发送。所以如果客户端处理消息“慢”,或者服务端发送消息“快”,则会导致客户端接收消息的时候会将那些未处理的正在队列中排队的消息都接收过来连成一条消息,导致信息处理出错。
这里用的是字符数组,而read读进来的是一个字节,所以会出现那种情形。
最终解决方法:
byte[] b = new byte[200];
int len;
while((len = is.read(b)) != -1) {
System.out.println(new Date());
String str = new String(b, 0, len);
System.out.println("我是服务器端,客户端说:"+ str);
}
总结:
readLine()这个方法本身有一个注意点,它读取的是一整行,遇见‘\n’或 ‘ \r’ 代表读取结束。因为用的是网络助手作为客户端 ,每次发送消息时并不会添加‘\n’,而用控制台作为客户端进行发送时,按下回车的时候就已经添加了‘\n’,所以服务器端进行接收的时候就是实时显示的。