1

I developed a tcp server in c working on linux. I remarked that if I make a stress connections on the server (keep refreshing with "F5" the address of the server on my web browser), then my server will be freezed.

I checked the netstat command, I found many socket opened on the server like this:

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

In my server code I already close the sockets with close(). These socket are kept opened even if I close my server. And if I restart it againg , then bind() return error (I think that because the sockets are not cleanly closed).

How to solve this problem?

How I can make my server not freezen even if there is a stress of connections?

How to force to be quicly closed in order to not get error in bind() when restarting my server?

Code:

#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;
}
alk
  • 69,737
  • 10
  • 105
  • 255
MOHAMED
  • 41,599
  • 58
  • 163
  • 268

1 Answers1

3

You may want to detach the threads you are creating.

Currently the threads are not detached, that means when they exit, their associated resources will not be freed (until joined, what you do not do) and with this will be eating up your machines resources (here: memory).

To detach a thread you could for example have it call pthread_detach() at the very beginning of the thread function:

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

Regarding the bind error you get when restarting your server you might like to read the answers to this question: What is the meaning of SO_REUSEADDR (setsockopt option) - Linux? on the use of the socket option SO_REUSEADDR.

Community
  • 1
  • 1
alk
  • 69,737
  • 10
  • 105
  • 255