ANSI C TCP/IP服务器联机客户端列表

ANSI C TCP/IP服务器联机客户端列表,c,multithreading,sockets,tcp,C,Multithreading,Sockets,Tcp,我编写了简单的TCP/IP多线程ANSIC服务器(客户端是C sharp),一切正常,除了服务器没有从客户端接收到正确的信号,它不会结束线程并关闭其套接字(例如,当客户端崩溃时)。如果这些线程累积起来,最终可能会成为问题。 我得到了存储在链表中的线程——遍历它们不是问题。但是,默认情况下,它们都被recv()阻止,并且由于死客户端不会发送任何内容,它们会被卡在内存中 维护在线客户列表的正确方法是什么?(或如何检测断开连接的线程) 螺纹代号: while(param->run) {

我编写了简单的TCP/IP多线程ANSIC服务器(客户端是C sharp),一切正常,除了服务器没有从客户端接收到正确的信号,它不会结束线程并关闭其套接字(例如,当客户端崩溃时)。如果这些线程累积起来,最终可能会成为问题。
我得到了存储在链表中的线程——遍历它们不是问题。但是,默认情况下,它们都被recv()阻止,并且由于死客户端不会发送任何内容,它们会被卡在内存中

维护在线客户列表的正确方法是什么?(或如何检测断开连接的线程)

螺纹代号:

while(param->run)
{
    bzero(&buf, sizeof(buf));
    if ((readLen = recv(param->c_sockfd, buf, BUFFSIZE, 0)) == -1)
    {
        perror("Read error");
        param->run = 0;
    }
    else if (readLen > 0) {
        printf("%s: %s \n", param->name, buf);

        parseIncoming(param->c_sockfd, param, buf);}}
下面是我检测断开连接的尝试,但这会导致服务器结束时没有消息:

void* maintenance() {
tListItem *item;
char buf[4] = "PNG";
while(1)
{
    usleep(2000000);
        item= threadList->head;
        while(item != 0)
        {
            if ((send(item->c_sockfd, buf, 3, NULL)) == -1)
            {
                perror("Write error");
                item->run = 0;
            }
            item = item->next;
        }
}

}

有几种常见的处理方法:

  • 在TCP之上的协议中实现心跳/乒乓。也就是说,定期更新客户端和/或服务器 向另一端发送心跳消息。如果服务器在一段时间内没有收到任何数据或心跳消息,例如心跳周期的两倍,或者如果从服务器发送心跳消息失败,则认为连接已经死亡并关闭它。

  • 实现总体数据超时。每次服务器接收数据时,您都会读取当前时间。定期检查连接以确定上次接收数据的时间,并超时/关闭一段时间内未接收数据的连接

  • 启用TCP keepalive。这基本上是一个最后的手段,如果你不能做到1。或者2。。它将帮助您检测死掉的对等点,因为如果无法联系到对等点,TCP keepalives将断开连接。(尽管它不会帮助您检测空闲客户端)。请注意,keepalives的默认值为小时数

  • 在所有情况下,您都应该始终处于read()/recv()状态,或者监视套接字中的read事件,以便在连接主动中断时尽可能快地学习


    如果要阻止read()/recv()调用,实现这一点也相当困难,通常需要在read()上设置一个超时,以便可以定期唤醒并发送心跳消息,或者检查客户端是否空闲太长时间-最好使用select()/poll()完成此操作或者诸如此类,这样您就可以得到一个超时,而不是执行可能永远不会返回的块读取()。

    我建议发布一些实际的代码。我想这将有助于更好的回应。
    void* maintenance() {
    tListItem *item;
    char buf[4] = "PNG";
    while(1)
    {
        usleep(2000000);
            item= threadList->head;
            while(item != 0)
            {
                if ((send(item->c_sockfd, buf, 3, NULL)) == -1)
                {
                    perror("Write error");
                    item->run = 0;
                }
                item = item->next;
            }
    }