简体   繁体   中英

c++ multithreaded server with std::thread casting variables

im just started coding in c++ and i am trying to build a multithreaded server but i got some errors. first, here is the code i got:

while(true){
        printf("waiting for a connection\n");
        csock = (int*)malloc(sizeof(int));

        if((*csock = accept( hsock, (sockaddr*)&sadr, &addr_size))!= -1)
        {
            printf("---------------------\nReceived connection from   %s\n",inet_ntoa(sadr.sin_addr));
            //std::thread th(&Network::SocketHandler, NULL);

            std::thread th(Network::SocketHandler, (void*)csock);
            th.detach();
        }
        else
        {
            fprintf(stderr, "Error accepting %d\n", errno);
        }
    }

    }


    void Network::SocketHandler(void* lp)
    {
        int *csock = (int*)lp;

       char buffer[1024];
       int buffer_len = 1024;
       int bytecount;

       memset(buffer, 0, buffer_len);
       if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){
          fprintf(stderr, "Error receiving data %d\n", errno);

       }
       printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
       strcat(buffer, " SERVER ECHO");

       if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){
          fprintf(stderr, "Error sending data %d\n", errno);

       }

       printf("Sent bytes %d\n", bytecount);

    }

i am getting a error when compiling at this line:

std::thread th(Network::SocketHandler, (void*)csock);

saying: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Network:: )(int ); _Args = {void*}] no known conversion for argument 1 from '' to 'void (Network:: &&)(int )'

how can i fix this? or is there a better way to create a multithreaded server any examples maybe of other posts?

Why are you passing in a void * instead of an int * when it's clear that what you really want is an int * ?

Just change the function signature to:

void Network::SocketHandler(int* csock)

and remove the cast in the code that does the calling:

std::thread th(Network::SocketHandler, csock);

Now, you will still get an error, and it will be for a different reason. Network::SocketHandler is a member function. It needs a this pointer. Normally you would call such functions with syntax like object.SocketHandler(csock) or objptr->SocketHandler(csock) . When you call it that way with ::std::thread you aren't giving it an object to be called on. It has no this pointer.

What you should do is change the function signature again to:

static void Network::SocketHandler(int* csock)

and then your code will work just fine. It doesn't look like the function makes use of any member variables, so it doesn't need a this pointer.

On a different note, it looks like you're trying to adapt something originally written for pthreads. If I were doing this for the C++11 thread library I would do it in a rather different manner.

I can't see your entire program, so I don't really have the luxury of re-designing it. But, from what I can see, I would make these tweaks:

while(true){
        printf("waiting for a connection\n");
        int csock = -1;

        if((csock = accept( hsock, (sockaddr*)&sadr, &addr_size))!= -1)
        {
            printf("---------------------\nReceived connection from   %s\n",inet_ntoa(sadr.sin_addr));
            //std::thread th(&Network::SocketHandler, NULL);

            std::thread th(Network::SocketHandler, csock);
            th.detach();
        }
        else
        {
            fprintf(stderr, "Error accepting %d\n", errno);
        }
    }

    }


    void Network::SocketHandler(int csock)
    {
       char buffer[1024];
       int buffer_len = 1024;
       int bytecount;

       memset(buffer, 0, buffer_len);
       if((bytecount = recv(csock, buffer, buffer_len, 0))== -1){
          fprintf(stderr, "Error receiving data %d\n", errno);

       }
       printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
       strcat(buffer, " SERVER ECHO");

       if((bytecount = send(csock, buffer, strlen(buffer), 0))== -1){
          fprintf(stderr, "Error sending data %d\n", errno);

       }

       printf("Sent bytes %d\n", bytecount);

    }

The changes are fairly subtle. The C++11 thread library lets you call functions and provide all their arguments, and it handles this in a thread-safe way. There is no need to pass void * anymore, nor is there a need to use malloc or new to create storage space for those arguments you can just pass the arguments your thread needs directly to the thread constructor.

Your program, in fact, has a memory leak. It never reclaims the space it malloc s for csock to point to. If it ran for a long time, it would eventually run out of memory as the space for all those filehandles was never reclaimed.

Your program may also have a filehandle leak. You do not appear to close the socket in Network::SocketHandler . But since I don't have visibility on your entire program, I can't be sure about that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM