简体   繁体   English

如何使用Java套接字检测数据丢失?

[英]How to detect dataloss with Java sockets?

I have the following situation: using a "classical" Java server (using ServerSocket) I would like to detect (as rapidly as possible) when the connection with the client failed unexpectedly (ie. non-gracefully / without a FIN packet). 我有以下情况:使用“经典” Java服务器(使用ServerSocket)我想(尽可能快地)检测到与客户端的连接意外失败(即,非优雅地/没有FIN数据包)。

The way I'm simulating this is as follows: 我模拟的方式如下:

  • I'm running the server on a Linux box 我在Linux机器上运行服务器
  • I connect with telnet to the box 我用telnet连接到盒子
  • After the connection has succeeded I add "DROP" rule in the box's firewall 连接成功后,在框的防火墙中添加“ DROP”规则

What happens is that the sending blocks after ~10k of data. 发生的情况是发送数据在大约10k之后阻塞。 I don't know for how long, but I've waited more than 10 minutes on several occasions. 我不知道待了多久,但我已经等了十多分钟了。 What I've researched so far: 到目前为止,我研究了什么:

  • Socket.setSoTimeout - however this affects only reads. Socket.setSoTimeout-但是,这仅影响读取。 If there are only writes, it doesn't have an effect 如果只有写,则没有效果
  • Checking for errors with PrintWriter.checkError(), since PW swallows the exceptions - however it never returns true 由于PW吞没了异常,因此使用PrintWriter.checkError()检查错误-但是,它永远不会返回true

How could I detect this error condition, or at least configure the timeout value? 如何检测到此错误情况,或者至少配置超时值? (either at the JVM or at the OS level) (在JVM或OS级别)

Update : after ~20min checkError returned true on the PrintWriter (using the server JVM 1.5 on a CentOS machine). 更新 :〜20分钟后,在PrintWriter上,checkError返回true(使用CentOS计算机上的服务器JVM 1.5)。 Where is this timeout value configured? 该超时值在哪里配置?

The ~20 min timeout is because of standard TCP settings in Linux. 〜20分钟超时是由于Linux中的标准TCP设置。 It's really not a good idea to mess with them unless you know what you're doing. 除非您知道自己在做什么,否则与他们混为一谈真的不是一个好主意。 I had a similar project at work, where we were testing connection loss by disconnecting the network cable and things would just hang for a long time, exactly like you're seeing. 我有一个类似的项目正在工作,我们正在通过断开网络电缆来测试连接丢失,结果就像您所看到的一样,它会长时间挂起。 We tried messing with the following TCP settings, which made the timeout quicker, but it caused side effects in other applications where connections would be broken when they shouldn't, due to small network delays when things got busy. 我们尝试弄乱下面的TCP设置,这使超时更快,但是它在其他应用程序中造成了副作用,这些应用程序在不应该建立连接的情况下会断开连接,这是由于繁忙时网络延迟很小。

net.ipv4.tcp_retries2
net.ipv4.tcp_syn_retries

If you check the man page for tcp (man tcp) you can read about what these settings mean and maybe find other settings that might apply. 如果查看手册页中的tcp(man tcp),则可以了解这些设置的含义,并可能找到其他可能适用的设置。 You can either set them directly under /proc/sys/net/ipv4 or use sysctl.conf. 您可以直接在/ proc / sys / net / ipv4下设置它们,也可以使用sysctl.conf。 These two were the ones we found made the send/recv fail quicker. 我们发现这两个使发送/接收失败更快。 Try setting them both to 1 and you'll see the send call fail a lot faster. 尝试将它们都设置为1,您会看到发送呼叫失败的速度更快。 Make sure to take not of the current settings before changing them. 更改之前,请确保不取当前设置。

I will reiterate that you really shouldn't mess with these settings. 我要重申的是,您确实不应该弄乱这些设置。 They can have side effects on the OS and other applications. 它们会对操作系统和其他应用程序产生副作用。 The best solution is like Kitson says, use a heartbeat and/or application level timeout. 最好的解决方案就像Kitson所说的那样,使用心跳和/或应用程序级别超时。

Also look into how to create a non-blocking socket, so that the send call won't block like that. 还要研究如何创建一个非阻塞套接字,以使send调用不会像这样阻塞。 Although keep in mind that sending with a non-blocking socket is usually successful as long as there's room in the send buffer. 尽管要记住,只要发送缓冲区中有空间,使用非阻塞套接字发送通常会成功。 That's why it takes around 10k of data before it blocks, even though you broke the connection before that. 这就是为什么在阻塞之前需要大约1万数据的原因,即使您在此之前断开了连接。

The only sure fire way is to generate application level "checks" instead of relying on the transport level. 唯一确定的方法是生成应用程序级别的“检查”,而不是依赖传输级别。 For example, a bi-directional heartbeat message, where if either end does not get the expected message, it closes and resets the connection. 例如,双向心跳消息,如果任一端未收到预期的消息,它将关闭并重置连接。

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

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