2015-11-30 14 views
0

我正在爲大學項目編寫網絡遊戲,雖然我在客戶端和服務器之間發送和接收消息,但我不確定如何執行writeable fd_set(我的講師的示例代碼僅包含在內一個readable fd_set)以及這兩個fd_sets與select()的函數是什麼。你可以提供的任何洞察力都能幫助我理解這一點。有人可以用WinSock解釋可寫和可讀fd_sets的功能嗎?

我的服務器代碼是這樣的:

bool ServerSocket::Update() { 
    // Update the connections with the server 

    fd_set readable; 
    FD_ZERO(&readable); 

    // Add server socket, which will be readable if there's a new connection 
    FD_SET(m_socket, &readable); 

    // Add connected clients' sockets 
    if(!AddConnectedClients(&readable)) { 
     Error("Couldn't add connected clients to fd_set."); 
     return false; 
    } 

    // Set timeout to wait for something to happen (0.5 seconds) 
    timeval timeout; 
    timeout.tv_sec = 0; 
    timeout.tv_usec = 500000; 

    // Wait for the socket to become readable 
    int count = select(0, &readable, NULL, NULL, &timeout); 
    if(count == SOCKET_ERROR) { 
     Error("Select failed, socket error."); 
     return false; 
    } 

    // Accept new connection to the server socket if readable 
    if(FD_ISSET(m_socket, &readable)) { 
     if(!AddNewClient()) { 
      return false; 
     } 
    } 

    // Check all clients to see if there are messages to be read 
    if(!CheckClients(&readable)) { 
     return false; 
    } 

    return true; 
} 

回答

-2

select()是非常過時的,它的界面顯得非常神祕。 poll(或它的窗口對應WSAPoll是現代替代它,並應總是優選

這將在下面的方式來使用:

WSAPOLLFD pollfd = {m_socket, POLLWRNORM, 0}; 
int rc = WSAPoll(&pollfd, 1, 100); 
if (rc == 1) { 
    // Socket is ready for writing! 
} 
+2

不以任何方式回答問題。 – EJP

+0

@EJP,怎麼樣?它完全告訴OP如何輪詢可寫入的套接字,並將OP指向適當的功能。未能看到它'不回答問題'。 – SergeyA

+0

問題是'有人可以解釋可寫和可讀fd_sets的功能'。你在這裏沒有解釋什麼。 – EJP

2

套接字變爲:

  • 可讀如果在套接字接收緩衝區或掛起的FIN中有數據(recv()即將返回零)
  • 如果套接字中有空間接收BU FFER。請注意,幾乎所有的時間都是這樣,所以只有當你在套接字上遇到以前的EWOULDBLOCK/EAGAIN時才應該使用它,並在你不使用它時停止使用它。
+0

那麼,這不會回答OP問題。 OP沒有詢問套接字是可寫的意味着什麼,OP詢問如何輪詢可寫狀態。說「套接字始終可寫」也是非常錯誤的。顯然,你從來沒有處理快速生產者/緩慢的消費者案件。 – SergeyA

+2

@Sergey OP明確地問道,我沒有說出你從我的話中捏造的錯誤。我把這個問題的標題轉給你,在文中重複,即*'有人可以解釋可寫和可讀的fd_sets'的功能,以及我實際寫的內容。 – EJP

3

你會創建一個fd_set變量稱爲writeable,初始化它以同樣的方式(與同一插座),並把它作爲select的第三個參數:

select(0, &readable, &writeable, NULL, &timeout); 

再經過select回報你'd檢查每個套接字是否仍在設置writeable。如果是這樣,那麼它是可寫的。

基本上,readable的工作原理完全一樣,只是它告訴你關於套接字的一個不同的東西。

+0

這對我很有意義。我不完全理解的是爲什麼我需要找出socket是否可寫。每當我發送一條消息時,是否需要檢查它是否可寫? – DeanoMachino

+0

@DeanoMachino'send'可以阻止,就像'recv'一樣。所以,類似的原因爲什麼你想知道一個套接字是否可讀 - 它並不重要,因爲'send'的發送頻率比'recv'少。 – immibis