繁体   English   中英

Java TCP / IP套接字如何向应用程序报告传输成功或失败?

[英]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.outSystem.err ),其中写输出失败不应停止应用程序(例如,如果没有标准输出可用)。

OutputStreamWriter替换它,一旦Java知道了错误,就会通知您。

这给我带来了第二个可能的问题:TCP / IP没有任何自动的保持活动数据包:因此, 如果您的连接以某种方式被切断,则在尝试发送数据之前您实际上不会注意到它。

因此,如果您连接到某个套接字,发送一些数据包,稍等片刻, 然后断开连接,则只有在下次尝试发送一些数据时,才会收到有关该事实的通知。 这是TCP / IP协议固有的,不是Java的错误。

如果要减少问题,则可以发送定期的保持活动/ ping消息,但没有实际效果,只是它们会检查连接是否仍然有效。

我会说你的问题足够不同。 Google对于这类事情有很多话要说。 保持活动( SO_KEEPALIVE )并非针对此类情况而设计。 从我读了TCP规范说他们应该超过每两小时一次发送,它是由你的操作系统来管理它,所以你没有太多的控制权。 从阅读的内容中强调。

但是,由于您一直在发送数据,因此是否每两个小时可以使用一次以上并不重要。 仅当您要在不发送数据时检测到断开的连接时,才需要保持活动状态。

如果直接使用SocketOutputStream ,则在尝试发送到不可用的目的地时(无论出于何种原因),它将引发异常。 由于使用的是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.

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