简体   繁体   English

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

[英]TCP Socket Hangs while receiving in Java

I am using a TCP Socket in my Java application. 我在Java应用程序中使用TCP套接字。 I am trying to receive byte data from some device with the readInt() method. 我正在尝试使用readInt()方法从某些设备接收字节数据。

This method works fine if I get 4 bytes from the device. 如果我从设备获取4个字节,则此方法可以正常工作。 But if I get less than 4 bytes, or nothing, then readInt() hangs. 但是,如果我得到的少于4个字节或什么都没有,则readInt()挂起。 It's blocked and doesn't return. 它被阻止,不会返回。 It should throw EOFException exception if no data is there to receive, but it's hanging. 如果没有要接收的数据,则应该抛出EOFException异常,但是它正在挂起。

Code: 码:

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

int res = din.readInt();

An EOFException doesn't get thrown until the socket closes. 在套接字关闭之前,不会引发EOFException

This method should block when you try to read more data than is available. 当您尝试读取的数据多于可用数据时,此方法应会阻塞。 It returns EOFException only when the socket closes, as this is the actual EOF condition. 它仅在套接字关闭时才返回EOFException,因为这是实际的EOF条件。 If the socket remains open, it blocks until it has enough data to fill the request. 如果套接字保持打开状态,它将阻塞直到它有足够的数据来填充请求。

This is part of the fundamental nature of the way sockets work. 这是套接字工作方式的基本本质的一部分。 For Java to behave any differently, it would have to incorrectly implement socket behavior. 要使Java的行为有所不同,就必须错误地实现套接字行为。

When putting together your socket protocol, you should consider this. 将套接字协议放在一起时,应该考虑这一点。 Why are you waiting for an int to be received and only part of an int is being sent? 为什么要等待一个int被接收并且仅发送int的一部分? This should never happen. 这永远都不会发生。 If you want to send different types of data, you should include some sort of header byte first to tell the receiver what kind of data is coming next so it knows how to process it and what to do with it. 如果要发送不同类型的数据,则应首先包含某种报头字节,以告知接收器接下来要接收哪种数据,以便知道如何处理数据以及如何处理数据。

That exception is probably only thrown when the other side of the connection closes the socket. 仅当连接的另一端关闭套接字时才会抛出该异常。 Otherwise the receiving side has no indication that no more data is going to come, so it waits (you did tell it to get at least four bytes when you called readInt ). 否则,接收方没有任何迹象表明将不再有数据,因此它将等待(调用readInt时,您告诉它至少要获取四个字节)。 You will have to read bytes and parse them into application blocks yourself. 您将必须读取字节并将其自己解析为应用程序块。

The classes you are using form part of the java.io package which performs blocking I/O. 您正在使用的类构成了执行阻塞 I / O的java.io包的一部分。 The correct solution is to switch to using the non-blocking I/O classes defined in java.nio . 正确的解决方案是切换到使用java.nio定义的非阻塞I / O类。 Be warned that writing a non-blocking I/O application is non-trivial. 请注意,编写非阻塞I / O应用程序并非易事。 However, it is the only solution to avoiding having your I/O thread potentially block indefinitely. 但是,这是避免I / O线程可能无限期阻塞的唯一解决方案。

Note that as a hacky solution you could use a dedicated blocking I/O thread that simply reads and adds bytes to a BlockingQueue being polled by another thread. 请注意,作为一种骇人听闻的解决方案,您可以使用专用的阻塞I / O线程,该线程仅读取并向另一个线程轮询的BlockingQueue添加字节。 The consumer thread could call poll(long, TimeUnit) on the BlockingQueue with a reasonably long time-out value, and if the call returned null it could take this to mean that no more data was available. 使用者线程可以使用相当长的超时值在BlockingQueue上调用poll(long, TimeUnit) ,如果调用返回null则可以认为这意味着没有更多数据可用。 Note that this is a fairly ugly solution as it means your I/O "producer" thread would remain blocked at this point. 请注意,这是一个非常丑陋的解决方案,因为这意味着您的I / O“生产者”线程将在此时保持阻塞状态。

That situation can only arise if you have mis-implemented your application protocol. 仅当您错误地实施了应用程序协议时,才会出现这种情况。 How come you're expecting a 4-byte integer and the application is only sending 1-3 bytes? 您为什么期望一个4字节的整数,而应用程序仅发送1-3个字节? Is it really sending a binary int? 它真的发送二进制int吗? or should you perhaps be reading and parsing an ASCII string? 还是应该阅读并解析ASCII字符串?

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

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