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

所以我想在Linux环境下学习C语言的socket编程选项SO_KEEPALIVE的用法。

我创build了一个服务器套接字,并使用我的浏览器连接到它。 这是成功的,我能够读取GET请求,但我卡住了SO_KEEPALIVE的用法。

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

只要我在accept()函数上检测到客户端的请求,我就在客户端套接字上设置SO_KEEPALIVE选项值1 。 现在我不知道如何检查客户端是否closures?如何改变发送探针之间的时间间隔等。

我的意思是我怎样才能得到客户端信号下降的信号(没有在客户端读取或写入的信息…我想我会得到一些信号,当客户端没有回应探测器时),设置选项后我应该如何编程SO_KEEPALIVE。

另外,如果假设探测器每3秒发送一次,并且客户端发生故障,我不会知道客户端已closures,我可能会收到SIGPIPE。

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

预先感谢吨!

Solutions Collecting From Web of "如何正确使用SO_KEEPALIVE选项来检测另一端的客户端是否已closures?"

要修改探测的数量或探测间隔,可以将值写入/ 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 

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

用keepalive不能从用户空间“检查”套接字的状态。 相反,内核只是强制远端确认数据包,并确定套接字是否坏。 当您尝试写入套接字时,如果keepalive已确定远程端已关闭,您将收到SIGPIPE。

如果启用SO_KEEPALIVE,则会得到相同的结果,就像不启用SO_KEEPALIVE一样 – 通常情况下,您会发现套接字已准备就绪,并在读取该套接字时发生错误。

您可以在Linux下以每个套接字为基础设置keepalive超时(这可能是Linux特有的功能)。 我推荐这个,而不是改变系统范围的设置。 有关更多信息,请参阅tcp的手册页。

最后,如果你的客户端是一个网页浏览器,它很可能会很快关闭套接字 – 它们大多数只会在相对较短的时间(30秒,1分钟等)内保持连接(HTTP 1.1)连接。 当然,如果客户端机器已经消失或者网络关闭(SO_KEEPALIVE对于检测来说真的很有用),那么它将无法主动关闭套接字。

正如已经讨论的那样,SO_KEEPALIVE使得内核更加激进,即使你没有做任何事情,也不断地验证连接,但不会改变或增强信息传递给你的方式。 你会发现什么时候你试图做某些事情(比如“写”),你会马上发现,因为内核现在只是报告之前设置的标志的状态,而不必等待一些秒(或者在某些情况下更长)网络活动失败。 你处理“另一侧意外”的确切代码逻辑仍将被使用; 时间(而不是方法)有什么变化。

实际上,每个“实际的”套接字程序都以某种方式在数据阶段提供对套接字的非阻塞访问(也许使用select()/ poll(),或者使用fcntl()/ O_NONBLOCK / EINPROGRESS&EWOULDBLOCK,或者如果你的内核支持也许与MSG_DONTWAIT)。 假设这已经是由于其他原因,这是微不足道的(有时不需要代码),另外找出一个连接丢失。 但是,如果数据阶段尚未以某种方式提供对套接字的非阻塞访问,那么直到下次尝试执行某些操作时,才会发现连接丢失。

(在数据阶段没有某种非阻塞行为的TCP套接字连接是非常脆弱的,就好像错误的数据包遇到网络问题一样,程序非常容易“无限期地挂起”,而且没有太多的东西可以做这件事。)