4

我有一个多线程客户端-服务器应用程序。第一个线程是一个“监听器”,它将客户端添加到文件描述符数组中:

while (1) {
    if ((connfd = accept(listenfd_service, (struct sockaddr *) &cliaddr, &clilen)) > 0) {
        printf("service connected...\n");
        int i;
        for (i = 0; i < MAX_SERVICES; i++) {
            if (service_sockets[i] == -1) {
                service_sockets[i] = connfd;
                break;
            }
        }
    }
}

问题是当我使用 Ctrl+C 终止客户端并运行以下行时

for (j = 0; j < MAX_SERVICES; j++) {
    if (service_sockets[j] != -1) {
        int test = write(service_sockets[j], c, 72);
        if (test == -1) {
            service_sockets[j] = -1;
        }
    }
}

我在“测试”变量中得到 72。如果我第二次尝试运行这些行,我会收到一个 SIGPIPE 信号。

4

1 回答 1

4

这是正常和预期的行为。当客户端退出时,服务器不会立即发现,因为通常当没有数据通过网络连接时,没有数据正在传输。相反,下次服务器发送数据时,它将发送一个数据包(即您成功写入 72 个字节),并且客户端计算机(如果操作系统仍在运行)将以“连接重置”消息进行响应。这将导致服务器操作系统关闭其连接端,从而在服务器下一次写入套接字时导致 SIGPIPE/EPIPE。

处理这个问题的正常方法是忽略 SIGPIPE 信号,并处理返回 EPIPE 错误的写入。几乎任何处理多个连接并且可能有一个连接而其他连接仍然有用的进程都需要忽略 SIGPIPE。

于 2012-06-08T19:31:36.600 回答