Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TCP套接字在Java中接收时挂起_Java_Sockets - Fatal编程技术网

TCP套接字在Java中接收时挂起

TCP套接字在Java中接收时挂起,java,sockets,Java,Sockets,我在Java应用程序中使用TCP套接字。我试图用readInt方法从某个设备接收字节数据 如果我从设备中获取4个字节,则此方法可以正常工作。但是如果我得到的字节少于4个,或者什么都没有,那么readInt将挂起。它已被阻止,无法返回。如果没有要接收的数据,但它挂起了,它应该抛出EOFEException异常 代码: 直到套接字关闭,才会抛出EOFEException 当您试图读取的数据超过可用数据量时,此方法应被阻止。它仅在套接字关闭时返回EOFEException,因为这是实际的EOF条件。如

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

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

代码:

直到套接字关闭,才会抛出EOFEException

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

这是套接字工作方式的基本特性的一部分。为了让Java的行为有所不同,它必须错误地实现套接字行为


当你把Socket协议放在一起时,你应该考虑这个问题。为什么要等待接收int,而只发送int的一部分?这永远不应该发生。如果要发送不同类型的数据,应首先包含某种类型的头字节,以告知接收方下一步将发送何种数据,以便接收方知道如何处理该数据以及如何处理该数据。

该异常可能仅在连接的另一端关闭套接字时才会引发。否则,接收方没有指示将不会有更多数据,因此它会等待您在调用readInt时告诉它至少获取四个字节。您必须自己读取字节并将其解析为应用程序块。

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


请注意,作为一个黑客解决方案,您可以使用一个专用的阻塞I/O线程,该线程只需读取并向另一个线程轮询的阻塞队列添加字节。使用者线程可以使用相当长的超时值调用BlockingQueue,如果调用返回null,则可能认为这意味着没有更多数据可用。请注意,这是一个相当丑陋的解决方案,因为这意味着您的I/O生产者线程此时仍将处于阻塞状态。

只有在错误实现应用程序协议时,才会出现这种情况。为什么您期望一个4字节的整数,而应用程序只发送1-3字节?它真的发送二进制整数吗?或者您是否应该读取和解析ASCII字符串?

是的,阻塞是一种自然行为。不,正确的解决方案是,当设备不发送4字节整数时,不要尝试读取4字节整数。@EJP:这将使您的应用程序任由设备摆布;如果设备存在bug,或者只是离线/无法访问,留下悬空的TCP套接字,应用程序线程将无限期地阻塞。因此,使用阻塞I/O并不是一个优雅的解决方案,这是完全错误的。只需设置读取超时。然后应用程序将仅在超时时间内阻塞,然后抛出SocketTimeoutException。这种情况并不能使java.nio成为“正确的解决方案”。这是许多中的一个。
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream   din = new DataInputStream(socket.getInputStream());

int res = din.readInt();