如何正确使用SO_KEEPALIVE选项来检测另一端的客户端是否已关闭?

Dur*_*rin 17 c sockets linux keep-alive

所以我试图在Linux环境下学习C语言的套接字编程中SO_KEEPALIVE选项的用法.

我创建了一个服务器套接字并使用我的浏览器连接到它.它很成功,我能够阅读GET请求,但我仍然坚持使用SO_KEEPALIVE.

我查了这个链接keepalive_description@tldg.org但我找不到任何显示如何使用它的例子.

一旦我在accept()函数上检测到客户端的请求,我就在客户端套接字上设置SO_KEEPALIVE选项值1.现在我不知道如何检查客户端是否已关闭?,如何更改探测发送之间的时间间隔等.

我的意思是如何获得客户端关闭的信号(无需在客户端读取或写入...我认为当探测器未从客户端回复时我会得到一些信号),如何在设置选项后对其进行编程SO_KEEPALIVE上.

此外,如果假设探测器每隔3秒发送一次并且客户端介于两者之间,我将不会知道客户端已关闭,我可能会收到SIGPIPE.

无论如何,重要的是我想知道如何在代码中使用SO_KEEPALIVE.

在此先感谢一吨!

bdk*_*bdk 21

要修改探测数或探测间隔,可以将值写入/ proc文件系统

 echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
 echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
 echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes
Run Code Online (Sandbox Code Playgroud)

请注意,这些值对于系统上所有启用了keepalive的套接字都是全局的.您还可以在设置setsockopt时基于每个套接字覆盖这些设置,请参阅所链接文档的第4.2节.

您无法使用keepalive从用户空间"检查"套接字的状态.相反,内核只是强迫远程端确认数据包,并确定套接字是否坏了.当您尝试写入套接字时,如果keepalive确定远程端已关闭,您将获得SIGPIPE.

  • 当您从套接字读取状态时,您会收到通知.如果由于keepalive确定对等体已死,则select/poll将不会将套接字视为可读,并且read()/ recv()将返回错误.无论如何,您应该始终读取或监视套接字以进行读取. (8认同)
  • @nirudh Tomer默认的keepalive探测器每2小时发送一次,如果它们之间75秒的9个探测器都失败,则对等体被确定为死亡.你是如何调整默认值的?请注意,tcp keepalive并非专门用于检测同伴的快速死亡.如果对等方仍然可以访问,则发送将失败,这没关系,您检测到它已经死亡!如果网络出现问题,快速检测死对等并不容易,通常也不可取. (4认同)

Mar*_*rkR 10

如果启用SO_KEEPALIVE,就会得到相同的结果,就好像你没有启用SO_KEEPALIVE一样 - 通常你会发现套接字就绪,并在读取时出错.

您可以在Linux下为每个插槽设置keepalive超时(这可能是特定于Linux的功能).我建议这样做而不是改变系统范围的设置.有关更多信息,请参见tcp的手册页.

最后,如果您的客户端是一个Web浏览器,它很可能会相当快地关闭套接字 - 大多数只会保持keepalive(HTTP 1.1)连接打开相对较短的时间(30秒,1分钟等).当然,如果客户端机器已消失或网络中断(这是SO_KEEPALIVE对检测非常有用),那么它将无法主动关闭套接字.

  • 在Windows中,您可以使用[WSAIoctl](http://msdn.microsoft.com/en-us/library/windows/desktop/dd877220%28v=vs.85%29.aspx)配置每插槽TCP keepalive设置. (2认同)