【问题标题】:All TCP clients terminates when one of the client is stopped当其中一个客户端停止时,所有 TCP 客户端都会终止
【发布时间】:2021-06-27 19:45:45
【问题描述】:

我正在尝试使用pthreads 在 C 中实现一个可以同时处理多个连接的 TCP 服务器。


服务器代码

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#include<readline/readline.h>
void* connection_handler(void *arg)
{
    int sock_number = *((int *)arg);
    printf("New connection with socket No. : %d\n",sock_number);
    char *message = "!!!!!!!!!!!!!!!!!! MESSAGE !!!!!!!!!!!!!!!!!!\n";
    while(1)
    {
        write(sock_number,message,strlen(message));
    }
}
int main()
{
    int sock_desc;
    sock_desc = socket(AF_INET,SOCK_STREAM,0);
    if(sock_desc<0)
    {
        perror("Socket error");
    }
    else
    {
        printf("Socket created!\n");
        struct sockaddr_in server,client;
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(8080);
        if(bind(sock_desc,(struct sockaddr*)&server,sizeof(server))<0)
        {
            perror("Binding error");
        }
        else
        {
            printf("Socket bound to 8080 port!\n");
            printf("Listening started.........\nWaiting for connections from clients.........\n");
            listen(sock_desc,20);
            int sock_size = sizeof(struct sockaddr_in);
            int new_socket;
            pthread_t pid[50];
            int connection_count=0;
            while((new_socket = accept(sock_desc,(struct sockaddr*)&client,(socklen_t*)&sock_size)))
            {
                printf("New connection : %s:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
                if(pthread_create(&pid[connection_count++],NULL,connection_handler,&new_socket)!=0)
                {   
                    perror("Thread error");
                }
            }
            for(int i=0;i<connection_count;i++)
            {
                pthread_join(pid[i],NULL);
            }
        }
    }
}

问题是当其中一个客户端停止时,整个服务器程序将同时终止,所有其他客户端也将终止。但是有多个连接没有问题。请告诉服务器为什么会终止即使客户端终止,有什么方法可以保持服务器运行?

【问题讨论】:

  • 看起来while((new_socket = accept(sock_desc,(struct sockaddr*)&amp;client,(socklen_t*)&amp;sock_size))) 将循环直到accept 返回零。 0 可能是可接受的套接字,accept 在错误时返回负数。杜尔。不,0 应该是标准输入。我认为你永远不会看到 0。
  • 线程不断地写入套接字。如果程序写入一个已经关闭的套接字,你应该得到一个 SIGPIPE,如果你没有正确处理它,程序就会崩溃。
  • 不要忘记检查来自write 的返回码,以便处理它吐出的错误。
  • ',&new_socket' 不,不安全。在处理程序线程可以取消引用指向它的指针之前,第二个连接可能会改变 new_socket:(
  • 唯一突出的是您通过引用线程例程传递new_socket。因此,如果多个客户端快速连续连接,它们就有可能都使用相同的套接字描述符。

标签: c server tcp pthreads


【解决方案1】:

我们看一下这段代码sn-p:

 while((new_socket = accept(sock_desc,(struct sockaddr*)&client,(socklen_t*)&sock_size)))
        {
            printf("New connection : %s:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
            if(pthread_create(&pid[connection_count++],NULL,connection_handler,&new_socket)!=0)
            {   
                perror("Thread error");
            }
        }
        for(int i=0;i<connection_count;i++)
        {
            pthread_join(pid[i],NULL);
        }

你有这个变量 new_socket。你有它的指针&new_socket。当客户端 1 连接时,您将 &new_socket 传递给 pthread,即线程 1。

然后您将连接客户端 2。您的变量 new_socket,具有相同的地址:&new_socket 然后将被传递给线程 2。这实际上意味着当您接受新连接时,您正在覆盖之前的套接字线程使用的变量。

这意味着如果第二个客户端连接,则在客户端 1 的线程 1 之前 执行int sock_number = *((int *)arg); 它们会导致执行线程重写传递给线程 1 的值,并且两个客户端将被同一个套接字引用

当一个客户端关闭套接字时,它们会关闭其他所有客户端使用的同一个套接字。

您的错误源于这样的想法,即通过接受实例化一个新的套接字对象,并使用一个新地址。情况并非如此,因为 C 没有对象。实际上,您对此套接字文件描述符的唯一引用是“int new_socket”,它是一个在整个 while 循环中保持相同地址的变量。

当你执行new_socket = accept(sock_desc,(struct sockaddr*)&amp;client,(socklen_t*)&amp;sock_size 时,这只是将套接字的文件描述符的值复制到new_socket。 解决此问题的一种简单方法是按值传递套接字:

void* connection_handler(void *arg)
{ 
 int sock_number = ((int)arg)
    ...
}

...

if(pthread_create(&pid[connection_count++],NULL,connection_handler,(void *)new_socket)!=0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-02
    • 2015-09-10
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多