[英]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 *
,也不需要使用malloc
或new
為那些參數創建存儲空間,您只需將線程需要的參數直接傳遞給線程構造函數即可。
實際上,您的程序存在內存泄漏。 它從不回收malloc
csock
給csock
指向的空間。 如果運行了很長時間,它將最終耗盡內存,因為所有這些文件句柄的空間都不會被回收。
您的程序也可能存在文件句柄泄漏。 您似乎沒有close
Network::SocketHandler
的套接字。 但是由於我對您的整個程序不了解,因此我不確定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.