2011-03-28 54 views
2

我正在編寫一個MUD服務器用於個人學習的目的,我愉快地設法將套接字填充到幾個類中,並且一切似乎都正常工作;服務器偵聽並接受連接,並且當前從客戶端獲取文本並將其發回。關於處理不好的電話接受()

事情是我不太確定如何調用accept(),它返回WSAEWOULDBLOCK或有效套接字以外的內容。我是否只是將新套接字重置爲0並返回,可能是錯誤消息說有什麼不好的事情發生?這就是我現在正在做的事情,如果發生了20次,我會關閉服務器。

void MUDControlSocket::Poll() 
{ 
    // create a new connection here 
    timeval timeout; 

    FD_ZERO(&ReadSet); 
    FD_ZERO(&WriteSet); 
    FD_ZERO(&ExceptionSet); 

    TopSocket = GetSocket(); 
    NewSocket = 0; 
    FD_SET(GetSocket(), &ReadSet); 

    if(SocketList.size() > 0) 
    { 
     for(sockIter iter = SocketList.begin(); iter != SocketList.end(); ++iter) 
     { 
     FD_SET((*iter)->GetSocket(), &ReadSet); 
     FD_SET((*iter)->GetSocket(), &WriteSet); 
     FD_SET((*iter)->GetSocket(), &ExceptionSet); 
     TopSocket = (*iter)->GetSocket(); 
     } 
    } 

    if(select(TopSocket+1, &ReadSet, &WriteSet, &ExceptionSet, &timeout) == SOCKET_ERROR) 
    { 
     cout << "Error on select() call: " << SocketErrorType(WSAGetLastError()) << endl; 

     delete this; 
     exit(EXIT_FAILURE); 
    } 

    // as long as everything is working correctly, this if block should always be entered UNLESS a new connection is accepted 
    if((NewSocket = accept(GetSocket(), NULL, NULL)) == INVALID_SOCKET) 
    { 
     if(WSAGetLastError() == WSAEWOULDBLOCK) // it's not an actual problem. just nothing to connect to yet 
     return; 
     NewSocket = 0; 
     static int count = 0; 
     cout << "Error on accepting new connection: " << SocketErrorType(WSAGetLastError()) << endl; 
     if(++count >= 20) 
     done = true; 
     return; 
    } 

    SocketList.push_back(new MUDSocket(NewSocket)); // only happens if accept DOES NOT return a value of INVALID_SOCKET i.e. a new connection was accepted 
    TopSocket = NewSocket; 
    NewSocket = 0; 
} 

TopSocket和NewSocket的類型是SOCKET,並在文件範圍聲明。 SocketList是MUDSocket *的std :: list,而MUDControlSocket是作爲單例從MUDSocket派生的。

讓我知道你是否需要更多的信息,並感謝您的任何幫助。

回答

0

第一:不要將套接字設置爲0:這是某些* NIX系統上套接字的有效fd,也是一個不好的習慣。假設唯一無效的套接字fd是-1。做任何事情都會在以後的真實軟件中給你帶來真正的錯誤(相信我:我是從調試使用0作爲無效套接字fd的代碼的經驗來講)。

除此之外,我會說只是引發一個異常:accept應該不會失敗,除非你用盡資源,這應該是例外和錯誤。 C++有處理這種事情的機制,這是例外。

順便說一句:delete this幾乎總是一個非常糟糕的想法,在代碼中間退出可能會導致難以調試(取而代之的是拋出異常)並讓調用者在需要時退出),而不是試圖接受一個帶有accept的套接字,你可以使用select來告訴你是否有任何東西可以接受 - 並將特殊情況處理移出該功能以僅在那裏選擇。你可以進一步實現一個專門的觀察​​模式(就像我在大約一個月前在my podcast上做的那樣),不僅練習你的網絡代碼,而且練習你的設計模式。這也有助於使代碼更加便於攜帶,並在以後重新使用。

HTH

+0

感謝您的信息。 – 2011-03-30 18:01:47

0

返回錯誤並讓調用代碼適當地處理它。

+0

整點是我不知道什麼是適當的方式來處理它。這並不是我計劃在其他地方使用的東西,至少現在不是,所以我正試圖就如何處理它提出一些想法。 – 2011-03-28 22:51:31

0

一些其他錯誤,從接受可能是內存不足,連接數耗盡,等等等等

也許它可以通過關閉不使用的或忘記的連接,或者乾脆放棄處理並拋出異常。

+0

我目前有一些代碼設置,從SOCKET_ERROR從套接字上的recv()返回時,將該錯誤的套接字拼接到另一個列表中,該列表在某些時候通過調用delete中的所有內容清除掉,然後清空名單。 – 2011-03-28 22:49:27