大家好,我想问一个 Socket 阻塞的问题

freehui_r 2015-07-08 03:21:16
加精
先看以下这几句代码(出自一个 Android 项目):


socket = new Socket();
socket.setSoTimeout(1000);
socket.connect(new InetSocketAddress(server ip ,port));
os = socket.getOutputStream();
is = socket.getInputStream();



以上代码是 Socket 初始化的代码,然后当我点击某个按钮时,最终就会调用到以下代码



os.write((byte[]) msg.obj); //这个 msg.obj 是我要发送给服务器的数据



当服务器接收到这些数据后,就会调用到以下代码。(服务器我是用 C 写的)



int ret[2];
char buf[100];

while (1){

/* 读出数据包 */
recv(client,buf,sizeof(buf),0);

//... 省略一堆处理数据的过程,在处理数据的时候,把两个要返回的值存放在了 ret 数组内

/* 返回结果,就是把 ret 数组写回去 */
send(client,ret,sizeof(ret),0);
}



接下来的重要了,是 JAVA 读取服务器返回值的代码,我是单独开了一个线程来读取服务器发来的数据的。



byte[] data = new byte[8];
...
/* 他本来的代码是这样的,但我发现他会在 is.read(data) 这里会不停地阻塞下去,所以我就把他修改了一下 */
is.read(data);
Message msg = new Message();
msg.obj = data;
main_handler.sendMessage(msg);
/* 改成了下面这样,发现就能正常读取数据了。 */
while (is.available() == 0)
Thread.sleep(1000);
is.read(data);
Message msg = new Message();
msg.obj = data;
main_handler.sendMessage(msg);



我的疑问是:为什么直接调用 read() 会出现无限阻塞的情况呢?怎么样才能在避免使用 available() 的情况下正常读出数据?本人小白,勿喷。。
...全文
2174 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
zi_yun_long 2015-07-24
  • 打赏
  • 举报
回复
楼主设置的socket超时时间是1s,数据到来前,超时,导致socket强制关闭。 socket.setSoTimeout(1000); 可以设置10000, 10s.
qq_30068799 2015-07-23
  • 打赏
  • 举报
回复
楼主最后解决了吗?
星小野 2015-07-19
  • 打赏
  • 举报
回复
我之前也有这样的问题! 解决方案: 实际上这个问题不是阻塞的问题,你的接收函数处理得到的结果一直是没有接收完整。看看client和server端的通讯模式是不是一致的。然后可以在接收的方法里面使用delegate进行你业务上的需要。 希望可以帮到你
zx627334118 2015-07-18
  • 打赏
  • 举报
回复
socket阻塞式IO就是这样的,只要你服务器没来数据,他就会一直等待,楼主可以用NIO
zoeg 2015-07-17
  • 打赏
  • 举报
回复
首先,InputStream.read(byte[])不是读够了才返回,当然,你可以测试1000+次发现每次都装满8个字节返回,但不能确保一定每次都是装满字节数组返回; 其次,根据之前的代码可以看出,阻塞似乎并不是你的主要问题,更重要的是你设置了socket.setSoTimeout(1000);导致read()并没有按照预期的方式一直阻塞知道收到数据,而是经常在超时时间到达之前就出错了; 最后,从一个流中读取数据光使用一次read是不够的, InputStream is=socket.getInputStream(); byte[] data=new byte[8]; int len,start=0; while((len=is.read(data,start,data.length-start))>0){ start+=len; if(start==data.length) break; } 写法大概是这样的,我没测试过,有些加加减减的事情自己调试下!
freehui_r 2015-07-17
  • 打赏
  • 举报
回复
引用 16 楼 zoeg 的回复:
首先,InputStream.read(byte[])不是读够了才返回,当然,你可以测试1000+次发现每次都装满8个字节返回,但不能确保一定每次都是装满字节数组返回; 其次,根据之前的代码可以看出,阻塞似乎并不是你的主要问题,更重要的是你设置了socket.setSoTimeout(1000);导致read()并没有按照预期的方式一直阻塞知道收到数据,而是经常在超时时间到达之前就出错了; 最后,从一个流中读取数据光使用一次read是不够的, InputStream is=socket.getInputStream(); byte[] data=new byte[8]; int len,start=0; while((len=is.read(data,start,data.length-start))>0){ start+=len; if(start==data.length) break; } 写法大概是这样的,我没测试过,有些加加减减的事情自己调试下!
没错,就是 setSoTimeout 的问题,我之前把他的功能理解错了,其实他就是 read 的超时时间!把他去掉就好了。 感谢。
qq_29865615 2015-07-16
  • 打赏
  • 举报
回复
楼主可以查看下API int java.io.InputStream.read(byte[] b) throws IOException Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown. 注意加粗部分
cattpon 2015-07-16
  • 打赏
  • 举报
回复
learning~
leslie914732486 2015-07-13
  • 打赏
  • 举报
回复
阻塞式调用读够了长度才会返回
qq_17410845 2015-07-13
  • 打赏
  • 举报
回复
都不记得了哦 。。。
freehui_r 2015-07-13
  • 打赏
  • 举报
回复
引用 11 楼 leslie914732486 的回复:
阻塞式调用读够了长度才会返回
服务器发来的数据长度是8字节,客户端用来接收数据的字节数组也是8字节
shuihan20e 2015-07-11
  • 打赏
  • 举报
回复
读够了长度才会返回
freehui_r 2015-07-11
  • 打赏
  • 举报
回复
引用 9 楼 shuihan20e的回复:
读够了长度才会返回
怎么会不够呢?服务器发来的数据长度是8字节,而客户端用来接收数据的字节数组也是8字节
freehui_r 2015-07-10
  • 打赏
  • 举报
回复
引用 6 楼 thc1987 的回复:
楼主可以查看下API int java.io.InputStream.read(byte[] b) throws IOException Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown. 注意加粗部分
那数据来到以后(input data is available),他就应该被唤醒啊,为什么他会一直阻塞下去呢?难道是没到输入流的末尾? 另外,为什么当 is.available() 检测到数据后再去读就能成功呢?他暗中做了什么手脚吗? 实在是 JAVA 小白,还望不吝赐教。
  • 打赏
  • 举报
回复
猿敲月下码 2015-07-10
  • 打赏
  • 举报
回复
楼主可以查看下API int java.io.InputStream.read(byte[] b) throws IOException Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown. 注意加粗部分
freehui_r 2015-07-10
  • 打赏
  • 举报
回复
引用 4 楼 bjym1987 的回复:
没发成功....?
肯定是发成功了的,如果没发成功的话,即使我加上 while (is.available() == 0) Thread.sleep(1000); 也应该读不到数据才对。
老王爱上猫 2015-07-09
  • 打赏
  • 举报
回复
没发成功....?
freehui_r 2015-07-08
  • 打赏
  • 举报
回复
引用 2 楼 suciver 的回复:
socket阻塞式IO就是这样的,只要你服务器没来数据,他就会一直等待,楼主可以用NIO
可是服务器已经往客户端发数据了啊。
send(client,ret,sizeof(ret),0);
suciver 2015-07-08
  • 打赏
  • 举报
回复
socket阻塞式IO就是这样的,只要你服务器没来数据,他就会一直等待,楼主可以用NIO
加载更多回复(1)

50,635

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧