2012-11-06 77 views
2

我試圖製作一個多客戶端服務器。我有這個線程:線程阻塞整個程序

void client_thread(int new_socket) 
{ 
    int size; 
    char inbuffer[BUF]; 

    do 
    { 
     cout << "Waiting for messages: " << endl; 
     size = recv(new_socket, inbuffer, BUF, 0); 
    } while (true); 
} 

,這主要過程:

int main() 
{ 
    while (true) 
    { 
     //waiting for clients 
     cout << "Waiting for connections..." << endl; 
     new_socket = accept (create_socket, (struct sockaddr *) &cliaddress, &addrlen); 

     //new client connected 
     if (new_socket > 0) 
     { 
      //start thread 
      thread(client_thread, new_socket).join(); 
     } 
    } 
    return 0; 
} 

當第一個客戶端連接,線程開始和服務器正在等待他的消息。但服務器不再等待新客戶。我不知道爲什麼。是否因爲線程函數內的無限循環do-while?如果他們包含無限循環會阻止整個程序,那麼線程的重點是什麼?

回答

6

主程序塊,因爲它等待線程完成:join()

如果你不想阻止,那麼你的client_thread不要join()

此異常可能來自您的匿名線程對象的破壞。當您離開if()的範圍時,此範圍內的所有對象都將被銷燬。從http://en.cppreference.com/w/cpp/thread/thread/~thread可以看到,析構函數調用terminate()。爲了避免它,你可以撥打detach()。因此,而不是thread(client_thread, new_socket).join();,你必須說thread(client_thread, new_socket).detach();

+1

如果我刪除'join()'程序崩潰,一旦客戶端連接以下消息:'終止調用沒有活動異常' – arminb

+0

什麼庫是'thread()'從哪裏來的?這是你寫的一個函數嗎?很難說爲什麼你會得到例外。 'join()'肯定會導致阻塞,並掩蓋了導致崩潰的問題。 –

+1

不,這不是自定義功能。它來自'std :: thread'(C++ 0x)。我也考慮過這樣編譯它:'g ++ -std = C++ 0x main.cpp -lpthread' – arminb

2

你應該創建一個線程,並保持一個引用,直到你加入它。在你的代碼中,線程對象在被創建後立即解除分配,因此如果不立即調用連接,則會出現錯誤。

要正確實現此目的,最好的方法是使用運算符new在堆上分配對象,並將指針存儲在某處的列表中。線程完成後,它可以從列表中刪除自己(不要忘記對其進行「互斥」),或者可以讓另一個專用線程執行該操作:也許您可以在退出之前讓主線程加入所有其他線程。