SO_KEEPALIVE:检测连接丢失或终止

时间:2013-05-02 18:18:41

标签: sockets keep-alive

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

客户端可能会退出或崩溃,或网络可能不好。

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

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。非常感谢。

1 个答案:

答案 0 :(得分:2)

如果保持活动失败,则操作系统将使连接无效,并且该套接字上的任何后续读/写操作都将失败并显示相应的错误代码。您需要确保您的读/写代码处理错误,以便它可以关闭套接字,如果它还没有这样做。