簡體   English   中英

具有std :: thread強制轉換變量的c ++多線程服務器

[英]c++ multithreaded server with std::thread casting variables

我剛剛開始用C ++編寫代碼,我正在嘗試構建多線程服務器,但是出現了一些錯誤。 首先,這是我得到的代碼:

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);

    }

在此行編譯時出現錯誤:

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

說:std :: thread :: thread(_Callable &&,_Args && ...)[with _Callable = void(Network :: )(int ); _Args = {void *}]沒有將參數1從''轉換為'void(Network :: &&)(int )'的已知轉換

我怎樣才能解決這個問題? 還是有更好的方法來創建多線程服務器?

當您清楚您真正想要的是int *時,為什么要傳遞void *而不是int *

只需將函數簽名更改為:

void Network::SocketHandler(int* csock)

並在執行調用的代碼中刪除強制類型轉換:

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

現在,您仍然會收到錯誤,並且原因有所不同。 Network::SocketHandler是成員函數。 它需要一個this指針。 通常,您可以使用諸如object.SocketHandler(csock)objptr->SocketHandler(csock)類的語法來調用此類函數。 當用::std::thread那樣調用它時,並沒有給它要調用的對象。 它沒有this指針。

您應該做的是再次將函數簽名更改為:

static void Network::SocketHandler(int* csock)

然后您的代碼就可以正常工作。 看起來該函數沒有使用任何成員變量,因此不需要this指針。

另一方面,您似乎正在嘗試改編最初為pthreads編寫的內容。 如果我在C ++ 11線程庫中執行此操作,則將以一種完全不同的方式執行。

我看不到您的整個程序,所以我真的沒有重新設計它的奢侈。 但是,據我所知,我將進行以下調整:

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);

    }

所做的更改相當微妙。 C ++ 11線程庫使您可以調用函數並提供其所有參數,並且它以線程安全的方式進行處理。 不再需要傳遞void * ,也不需要使用mallocnew為那些參數創建存儲空間,您只需將線程需要的參數直接傳遞給線程構造函數即可。

實際上,您的程序存在內存泄漏。 它從不回收malloc csockcsock指向的空間。 如果運行了很長時間,它將最終耗盡內存,因為所有這些文件句柄的空間都不會被回收。

您的程序也可能存在文件句柄泄漏。 您似乎沒有close Network::SocketHandler的套接字。 但是由於我對您的整個程序不了解,因此我不確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM