繁体   English   中英

使用Java接收时TCP套接字挂起

[英]TCP Socket Hangs while receiving in Java

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

如果我从设备获取4个字节,则此方法可以正常工作。 但是,如果我得到的少于4个字节或什么都没有,则readInt()挂起。 它被阻止,不会返回。 如果没有要接收的数据,则应该抛出EOFException异常,但是它正在挂起。

码:

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

int res = din.readInt();

在套接字关闭之前,不会引发EOFException

当您尝试读取的数据多于可用数据时,此方法应会阻塞。 它仅在套接字关闭时才返回EOFException,因为这是实际的EOF条件。 如果套接字保持打开状态,它将阻塞直到它有足够的数据来填充请求。

这是套接字工作方式的基本本质的一部分。 要使Java的行为有所不同,就必须错误地实现套接字行为。

将套接字协议放在一起时,应该考虑这一点。 为什么要等待一个int被接收并且仅发送int的一部分? 这永远都不会发生。 如果要发送不同类型的数据,则应首先包含某种报头字节,以告知接收器接下来要接收哪种数据,以便知道如何处理数据以及如何处理数据。

仅当连接的另一端关闭套接字时才会抛出该异常。 否则,接收方没有任何迹象表明将不再有数据,因此它将等待(调用readInt时,您告诉它至少要获取四个字节)。 您将必须读取字节并将其自己解析为应用程序块。

您正在使用的类构成了执行阻塞 I / O的java.io包的一部分。 正确的解决方案是切换到使用java.nio定义的非阻塞I / O类。 请注意,编写非阻塞I / O应用程序并非易事。 但是,这是避免I / O线程可能无限期阻塞的唯一解决方案。

请注意,作为一种骇人听闻的解决方案,您可以使用专用的阻塞I / O线程,该线程仅读取并向另一个线程轮询的BlockingQueue添加字节。 使用者线程可以使用相当长的超时值在BlockingQueue上调用poll(long, TimeUnit) ,如果调用返回null则可以认为这意味着没有更多数据可用。 请注意,这是一个非常丑陋的解决方案,因为这意味着您的I / O“生产者”线程将在此时保持阻塞状态。

仅当您错误地实施了应用程序协议时,才会出现这种情况。 您为什么期望一个4字节的整数,而应用程序仅发送1-3个字节? 它真的发送二进制int吗? 还是应该阅读并解析ASCII字符串?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM