java的socket通讯,使用readLine接收还是使用read接收

Socket s = new Socket("192.168.218.2", 58100);

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

String info = null;

while(!((info=br.readLine())==null)){

    System.out.println(info);

    }

以上是部分代码,主要是readLine这句,接收字符串的时候,最后一行接收不到,while之后的代码也没有执行,程序处于一个挂起的状态。

上网查了下资料,好像是说最后一行没有回车符,我在服务端加了回车符之后,还是跳不出循环。。。


解决:

readLine只有读取文件等的结尾才会是null

在网络上(都是阻塞模式),readLine是一直等待输入,

即使是对方什么也不输入,只是回车,readLine也不会返回null,所以无法跳出while循环。


在I/O阻塞模式下,你写的条件循环while((line = in.readLine()) != null)是不合理的。

两种方法解决:

(1)双方约定每次发送报文都报文前几个字符表示长度信息,如下

原始报文是:ASDF

发送的socket报文是:0004ASDF

其中0004表示报文长度,接收方先接收四位的长度,再接收余下的报文。


(2)双方约定一个特殊的标志是结束符,比如约定 ==END== 表示结束

代码修改为while(!"==END==".equals(line = in.readLine()))就继续等待接收

这个特殊的结束符需要双方发送报文结束必须再发送的。


第一种解决方法是最常用的。自己接触的几个项目都是此种方式。

附加第一种方法的用法:

byte[] msgHead = new byte[5];// 双方约定前五位表示报文长度

in.read(msgHead, 0, msgHead.length);// 首先读取报文长度信息

String msgLength = new String(msgHead, getEncoding());

int msgLengthInt = Integer.parseInt(msgLength);

byte[] msgBody = new byte[msgLengthInt];// new一个报文长度大小的字节数组

in.read(msgBody, 0, msgBody.length);// 读取报文信息

byte[] recMsg = new byte[msgHead.length + msgBody.length];// 如有需要合并报文长度和报文信息

System.arraycopy(msgHead, 0, recMsg, 0, msgHead.length);

System.arraycopy(msgBody, 0, recMsg, msgHead.length, msgBody.length);


第二种方式,要双方约定一个结束符才能工作,而且存在bug。

对于很多特殊字符或者字节等在传输中转换为String会失真,则双方无法正常通讯。

例如:

byte[] b1 = new byte[10];

for (int i = 0; i < 10; i++) {

b1[i] = (byte) (i - 5);

}

byte[] b2 = new String(b1).getBytes();

for (int i = 0; i < 10; i++) {

System.out.println(b1[i] + " <-> " + b2[i]);

}

输出结果显示byte[]在转换为String在转换为byte[]时候已经失真。

byte[] --> String --> byte[] 发生失真问题参见另一篇文章

http://blog.csdn.net/fl772333621/article/details/10162447


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值