Socket通讯读取数据时阻塞解决方案

    |     2017年8月25日   |   Java网络编程   |     0 条评论   |    1925

读文件时 read 读到末尾会返回 -1。但 Socket 通讯里从 InputStream 读数据,对端还没关流、暂时又没有数据时,read 会一直阻塞,只有关闭流才会返回 -1。

所以下面这种「读到 -1 才停」的写法,在 Socket 上很容易卡住:

while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
}

一、每发一次就开关连接

每发送一次消息开启 Socket 连接,发完关闭。关流后服务端 read 就能拿到 -1,循环结束。

Socket 服务端接收消息:

ServerSocket serverSocket = new ServerSocket(port);
while(true){
socket = serverSocket.accept();
receiveMessage();//接收消息
}

Socket客户端发送消息:
socket = new Socket(host, port);  //发起连接
client.sendPicture(fileDir); //发送消息

二、先发文件大小

客户端先把文件字节大小写过去,服务端累计读到的字节数,够了就 break,不必等流关闭。

Socket客户端:
dos.writeLong(file.length()); //文件字节大小
Sokcet服务端:
//读取图片大小
long picLength = dos.readLong();
//图片文件内容
byte[] bytes = new byte[128];
int len = 0;
int count = 0; //统计读取流总字节数
while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
count = count + len;
if(count == picLength){ //接收数据大小与文件大小比较
break;
}
}

三、设置读超时

用 socket.setSoTimeout 设读超时。一段时间没数据就抛 IOException,循环被打断;处理完再把超时设回 0(无穷大)。

Socket服务端:
try {
byte[] bytes = new byte[128];
int len = 0;
socket.setSoTimeout(10); //设置socket读超时时间为10毫秒
while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
}
} catch (IOException e) {
System.out.println("接收图片成功!");
socket.setSoTimeout(0);//设置socket读超时时间为无穷大
}
方案 做法 何时结束读循环
开关连接 发完就关 Socket 对端关流,read 返回 -1
先发长度 writeLong(file.length()) 累计字节数等于文件大小则 break
读超时 setSoTimeout(10) 超时抛 IOException

一句话总结:Socket 的 read 没数据会阻塞,别只等 -1;用关连接、先传长度或 setSoTimeout 才能停下来。

转载请注明来源:Socket通讯读取数据时阻塞解决方案
本文链接地址:https://ai.zhousir.top/?p=2132

上一篇:

下一篇:

回复 取消