我在Java应用程序中使用TCP Socket。我试图使用readInt()
方法从某些设备接收字节数据。
如果我从设备获得4个字节,此方法可以正常工作。但是如果我得到的字节少于4个字节,或者什么都没有,那么readInt()
就会挂起。它被阻止而且不会返回。 1}}如果没有数据可以接收,它应该抛出EOFException
异常,但它已经挂起了。
代码:
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream din = new DataInputStream(socket.getInputStream());
int res = din.readInt();
答案 0 :(得分:4)
在套接字关闭之前,EOFException
不会被抛出。
当您尝试读取的数据超出可用数量时,此方法应阻止。它仅在套接字关闭时返回EOFException,因为这是实际的EOF条件。如果套接字保持打开状态,它将一直阻塞,直到它有足够的数据来填充请求。
这是套接字工作方式的基本特征。对于Java的行为方式不同,它必须错误地实现套接字行为。
在整合套接字协议时,您应该考虑这一点。你为什么要等一个int被接收,只有部分int被发送?这绝不应该发生。如果要发送不同类型的数据,首先应该包含某种头字节,以告诉接收者接下来会有哪种数据,以便知道如何处理它以及如何处理它。
答案 1 :(得分:1)
当连接的另一端关闭套接字时,可能只会引发该异常。否则接收方没有迹象表明将不再有数据,所以它等待(当你调用readInt
时,你确实告诉它至少得到4个字节)。您必须自己读取字节并将其解析为应用程序块。
答案 2 :(得分:0)
您正在使用的课程是执行阻止 I / O的java.io
包的一部分。正确的解决方案是切换到使用java.nio
中定义的非阻塞I / O类。请注意,编写非阻塞I / O应用程序并非易事。但是,这是避免让I / O线程无限期阻塞的唯一解决方案。
请注意,作为一个hacky解决方案,您可以使用专用的阻塞I / O线程,该线程只读取并向另一个线程轮询的BlockingQueue
添加字节。消费者线程可以使用相当长的超时值在BlockingQueue
上调用poll(long, TimeUnit)
,如果调用返回null
,则可能意味着没有更多数据可用。请注意,这是一个相当丑陋的解决方案,因为这意味着此时I / O“生产者”线程将保持阻塞状态。
答案 3 :(得分:0)
只有在您错误地实施了应用程序协议时才会出现这种情况。你怎么期望一个4字节的整数,应用程序只发送1-3个字节?它真的发送二进制int吗?或者您是否应该阅读并解析ASCII字符串?