2015-09-25 70 views
0

我想實現一個小的c + +服務器。我想要接收來自客戶端的連接,並在自己的線程中處理所有這些連接。到現在爲止還挺好。只要我沒有引入線程,它的工作正常,但只要我嘗試爲客戶端創建線程,接受返回與-1 /錯誤。C++線程+網絡,只要我介紹線程接受失敗

這裏是我的代碼:

void Server::run() 
{ 
    cout << "starting server on port " << this->port << "..." << endl; 

    this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); 
    if (this->socket_fd < 0) { 
    perror("creating socket"); 
    exit(1); 
    } 

    struct sockaddr_in myaddr; 
    myaddr.sin_family = AF_INET; 
    myaddr.sin_port = htons(this->port); 
    inet_aton("192.168.201.58", &myaddr.sin_addr); 

    if (bind(this->socket_fd, (struct sockaddr*)&myaddr, sizeof(myaddr))) { 
    perror("bind"); 
    exit(1); 
    } 
    if (listen(this->socket_fd, 5)) { 
    perror("listen"); 
    exit(1); 
    } 

    /* waiting for clients */ 
    cout << "waiting for connection..." << endl; 
    int client_fd; 
    struct sockaddr_in remote_addr; 
    socklen_t remote_addr_len; 

    while (this->running) { 
    client_fd = accept(this->socket_fd, (struct sockaddr*)&remote_addr, &remote_addr_len); 
    if (client_fd <= 0) { 
     perror("accept"); 
     this->running = false; 
     continue; 
    } 

    cout << "got new client with address " << inet_ntoa(remote_addr.sin_addr) << endl; 

    Client new_client(client_fd, remote_addr.sin_addr); 
    //new_client.run(); 
    std::thread t (&Client::run, &new_client); 
    //t.detach(); 
    } 
} 

當我試圖通過telnet連接時,我得到「接受:無效的參數」。只要我註釋掉我創建線程的線路

std::thread t (&Client::run, &new_client); 

一切工作正常。

我會很感激任何提示。

+0

您傳遞的線程即將超出範圍的對象的地址。在線程運行時,'new_client'可能不再存在。兩個明顯的解決方案:1)使用'make_shared'創建客戶端對象,並將線程'shared_ptr'傳遞給它。 2)通過值傳遞線程描述符和地址,讓線程創建客戶端對象。 –

+0

感謝您的提示!所以我改變了new_client動態分配:'while(this-> running){client_fd = accept(this-> socket_fd,(struct sockaddr *)&remote_addr,&remote_addr_len);如果(client_fd <= 0){ \t \t \t \t \t this-> running = false; \t \t \t繼續; \t \t} \t \t Client * new_client = new Client(client_fd,remote_addr.sin_addr); \t} '並刪除線程。仍然是接受失敗的相同問題。 – user1816723

+0

您需要在每次調用accept之前初始化'remote_addr_len'。 –

回答

-1

嘗試:

std::thread t (&Client::run, std::move(new_client)); 

the documentation,這就是你應該怎麼稱呼它。

+0

我假設你的意思是'std :: thread t(&Client :: run,std :: ref(new_client));否則我得到一個編譯器錯誤。但無論如何,這兩種變體都不能解決問題。 – user1816723

+0

線程應該怎樣處理一個不再存在的對象的引用? –

+0

是的,修復了和丟失。另外,我非常肯定,如果你使用std :: move,它將解決new_client超出範圍的問題。 – tstark81