sockets - SO_KEEPALIVE : Detecting connection lost or terminated

标签 sockets keep-alive

我有多个线程,每个线程都有一个与客户端应用程序打开的套接字。这些线程中的每一个都从主线程接收指令以向客户端发送命令(命令可以是运行测试、停止测试、终止 session 、退出......)。这些线程是通用的,它们每个客户端只有一个套接字,并且只在主线程要求时发送命令。

客户端可能退出或崩溃,或者网络可能很糟糕。

我一直在尝试了解如何确定每个客户端的 TCP session 已结束。我发现两个解决方案似乎适合这里。

1)实现自己的心跳系统 2)通过setsockopt使用keepAlive。

我尝试过2),因为它听起来实现起来更快,但我不确定一件事:当连接中断时SO_KEEPALIVE会生成SIGPIPE吗?我看到应该是这样,但从未收到过 SIGPIPE。

这就是我的代码的样子:

void setKeepAlive(int sockfd) {
    int optval;

    optval = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
    optval = 1;
    setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
    optval = 1;
    setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval));
    optval = 1;
    setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval));
}

我接受连接的代码如下:

for (mNumberConnectedClients = 0; mNumberConnectedClients < maxConnections; ++mNumberConnectedClients) {
    clientSocket = accept(sockfd, (struct sockaddr *) &client_addr, &clientLength);

    // set KeepAlive on socket
    setKeepAlive(clientSocket);

    pthread_create(&mThread_pool[mNumberConnectedClients], NULL, controlClient, (void*) &clientSocket);
}

signal(SIGPIPE, test);
....

以及测试函数:

void test(int n) {
    printf("Socket broken: %d\n", n);
}

test() 永远不会被触发。请问是我的理解有误吗?我不确定 SIGPIPE 是否生成。非常感谢。

最佳答案

如果保持事件失败,操作系统将简单地使连接无效,并且该套接字上的任何后续读/写操作都将失败并显示相应的错误代码。您需要确保您的读/写代码正在处理错误,以便它可以关闭套接字(如果尚未这样做)。

关于sockets - SO_KEEPALIVE : Detecting connection lost or terminated,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16345013/

相关文章:

yii2 - yii2 有持久连接选项吗?

http - Golang 如何使用 keepalive 处理优雅关机

java - 通过套接字发送字符串。服务器没有收到

windows - 用于 I/O 的最新 Windows 线程池 API 用法

c# - 通过套接字发送对象

java - 如何在 UDP 协议(protocol)上同步通信?

java - JFrame 中的问题

node.js - 如何让 Node 服务器永久保持事件状态?

java - 从应用程序外部测试应用程序服务的最佳方法

http - 将 JPEG 图像从 HTTP multipart/x-mixed-replace keep-alive 流保存到 ubuntu 服务器