[英]How do Java TCP/IP sockets report transmission success or failure to the application?
我在使用Java TCP / IP套接字时遇到问题:即使在此期间服务器关闭(没有正确的TCP / IP断开连接),我的Java应用程序也将不断向服务器发送数据。
我正在使用以下代码发送数据:
PrintWriter out = PrintWriter(socket.getOutputStream(), true);
out.write("text");
if (out.checkError()) {
System.err.println("Error sending string!");
}
在另一个Stack Overflow问题中 ,我找到了以下答案:
TCP / IP(以及Java套接字)将确保您最终成功发送数据或获得错误(对于Java除外)。
我的代码是否足以通知TCP / IP堆栈而无法成功发送我的字符串,或者我是否需要做其他事情?
顺便说一句:即使另一个问题相似,打开一个新问题是否正确? 它不能令人满意地回答我的问题,我只能添加一个新答案,而不能添加新评论。
您可能有两个问题: PrintWriter
是Java Stream
/ Reader
/ Writer
中的一头Writer
,因为它吞噬了异常并要求您显式检查错误。
对此的唯一用途(在我看来)是标准流( System.out
和System.err
),其中写输出失败不应停止应用程序(例如,如果没有标准输出可用)。
用OutputStreamWriter
替换它,一旦Java知道了错误,就会通知您。
这给我带来了第二个可能的问题:TCP / IP没有任何自动的保持活动数据包:因此, 如果您的连接以某种方式被切断,则在尝试发送数据之前您实际上不会注意到它。
因此,如果您连接到某个套接字,发送一些数据包,稍等片刻, 然后断开连接,则只有在下次尝试发送一些数据时,才会收到有关该事实的通知。 这是TCP / IP协议固有的,不是Java的错误。
如果要减少问题,则可以发送定期的保持活动/ ping消息,但没有实际效果,只是它们会检查连接是否仍然有效。
我会说你的问题足够不同。 Google对于这类事情有很多话要说。 保持活动( SO_KEEPALIVE
)并非针对此类情况而设计。 从我读了TCP规范说他们不应该超过每两小时一次发送,它是由你的操作系统来管理它,所以你没有太多的控制权。 我从阅读的内容中强调。
但是,由于您一直在发送数据,因此是否每两个小时可以使用一次以上并不重要。 仅当您要在不发送数据时检测到断开的连接时,才需要保持活动状态。
如果直接使用Socket
的OutputStream
,则在尝试发送到不可用的目的地时(无论出于何种原因),它将引发异常。 由于使用的是PrintWriter
,因此需要使用checkError()
手动检查错误。
因此,总而言之:是的,它足以满足您的目的。
我没有提到(因为当时我认为它不相关)是我正在尝试在Android上执行此操作。
经过几周的测试,Android似乎对标准Java网络类的实现与Oracle JRE的行为却大不相同。 在Android上,即使我自己关闭了连接,显然也无法可靠地检测连接是否已关闭。 [Stream].write()
将尝试写入几分钟。 因此,在Android上,似乎总是需要发送自己的保持活动状态(并检查接收状态!)才能检测到断开的连接。
该问题的其他答案将与Oracle JRE配合使用。 再次感谢!
如果有人可以提供有关此主题的更多信息,请这样做。
有时,即使服务器已死亡,也不会通知您的客户端应用程序。 通常,这是一个无法关闭连接双方的坏路由器。 您应该设置保持活动状态,以便可以检测到这种故障。
根据您的操作系统,有多种方法可以更改保持活动测试间隔。
关闭插座时,有一种特殊条件。 根据您设置的套接字opt SO_LINGER
(请参阅本文 ), close()
调用将立即返回或等待,直到所有挂起的TCP传输成功或发生错误为止,然后由close()
引发IOException来发出信号close()
实施。
SO_TIMEOUT
也影响重试何时超时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.