TCP Socket在Java中接收时挂起

时间:2010-10-29 13:30:32

标签: java sockets

我在Java应用程序中使用TCP Socket。我试图使用readInt()方法从某些设备接收字节数据。

如果我从设备获得4个字节,此方法可以正常工作。但是如果我得到的字节少于4个字节,或者什么都没有,那么readInt()就会挂起。它被阻止而且不会返回。 EOFException异常,但它已经挂起了。

代码:

DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream   din = new DataInputStream(socket.getInputStream());

int res = din.readInt();

4 个答案:

答案 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字符串?