【问题标题】:server freezing after many linux sockets许多Linux套接字后服务器冻结
【发布时间】:2014-09-26 10:17:49
【问题描述】:

我用 c 语言开发了一个在 linux 上工作的 tcp 服务器。 我说如果我在服务器上建立压力连接(在我的网络浏览器上用“F5”刷新服务器的地址),那么我的服务器将被冻结。

我检查了netstat 命令,我发现服务器上打开了很多这样的套接字:

tcp        0      0 192.168.1.211:7547      192.168.1.133:10073     TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:9985      TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:9967      TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:10041     TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:10027     TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:10042     TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:10016     TIME_WAIT
tcp        0      0 192.168.1.211:7547      192.168.1.133:9993      TIME_WAIT

在我的服务器代码中,我已经用close() 关闭了套接字。 即使我关闭服务器,这些套接字也会保持打开状态。如果我重新启动它,那么bind() 返回错误(我认为这是因为套接字没有完全关闭)。

如何解决这个问题?

即使存在连接压力,我如何才能使我的服务器不冻结?

如何强制快速关闭以便在重新启动我的服务器时不会在bind() 中出现错误?

代码:

#include<stdio.h>
#include<string.h>    //strlen
#include<stdlib.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write
#include<pthread.h> //for threading , link with lpthread

struct http_cr_data {
    int client;
    int count;
};

void *thread_serv_new_client(void *v)
{
    int count;
    int client;
    struct http_cr_data *crd = (struct http_cr_data *)v;
    count = crd->count;
    client = crd->client;
    free(crd);

    printf("(%d) Received message by the server!\n", count);
    close(client);
    return NULL;
}

void server_init(void)
{
    int socket_desc , client_sock , c, count=0 , *new_sock;
    struct sockaddr_in server , client;

    for(;;) {
        //Create socket
        socket_desc = socket(AF_INET , SOCK_STREAM , 0);
        if (socket_desc == -1)
        {
            printf ("Could not open server socket for Connection Requests, Trying again");
            sleep(1);
            continue;
        }

        //Prepare the sockaddr_in structure
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(7547);

        //Bind
        if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
        {
            //print the error message
            printf ("Could not bind server socket for Connection Requests, Trying again");
            sleep(1);
            continue;
        }
        break;
    }

    printf ("Connection Request server initiated");

    //Listen
    listen(socket_desc , 3);

    //Accept and incoming connection
    c = sizeof(struct sockaddr_in);
    while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        pthread_t serv_cr__thread;
        struct http_cr_data *crd = malloc(sizeof (struct http_cr_data));
        crd->count = ++count;
        crd->client = client_sock;

        int error = pthread_create(&serv_cr__thread, NULL, &thread_serv_new_client, (void *)crd);
       if (error<0)
       {
           printf ("Error when creating Connection Request thread!");
       }
    }

    if (client_sock < 0)
    {
        printf ("Could not accept connections for Connection Requests!");
        return;
    }
}

int main() {
    server_init();
    return 0;
}

【问题讨论】:

  • 你试过使用非阻塞套接字吗?
  • @VladimirKocjancic 非阻塞套接字??
  • 两个很可能与问题无关的细节:1. 这个if (error&lt;0) 应该是if (error!=0)2。 c 应为 socklen_t 类型。
  • 另外:while( (client_sock = accept(... 应为 while (0 &lt;= (client_sock = accept(...
  • @VladimirKocjancic:这与使用的套接字是阻塞的还是非阻塞的无关。

标签: c++ c linux sockets pthreads


【解决方案1】:

您可能想要分离正在创建的线程。

当前线程没有分离,这意味着当它们退出时,它们的相关资源将不会被释放(直到加入,你不做的事情),这将消耗你的机器资源(这里:内存)。

要分离一个线程,你可以让它在线程函数的最开始调用pthread_detach()

void *thread_serv_new_client(void *v)  
{
  pthread_detach(pthread_self());

关于重新启动服务器时遇到的绑定错误,您可能想阅读以下问题的答案:What is the meaning of SO_REUSEADDR (setsockopt option) - Linux? on the use of the socket option SO_REUSEADDR

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    相关资源
    最近更新 更多