2011-11-12 122 views
1

我有一個簡單的服務器/客戶端程序,我正在處理。我正在使用select()等待數據在讀取之前進入TCP套接字。當數據進入時,我使用幾個recv()select()調用來讀取塊,直到我擁有了全部數據。然後,我循環回到最初的select()調用,並查看客戶端是否有其他要發送的內容。套接字選擇()第二次阻塞

struct timeval timeoutCounter; 
fd_set readFileDescriptor; 
do { 
    timeoutCounter.tv_sec = 30; 
    timeoutCounter.tv_usec = 0; 
    FD_ZERO(&readFileDescriptor); 
    FD_SET(socket, &readFileDescriptor); 
    cout << "This line always prints, every iteration through the loop.\n"; 
    dataReady = select(socket+1,&readFileDescriptor,NULL,NULL,&timeoutCounter); 
    cout << "This line only prints the first time I call select()." 
     << "The second time it hangs before reaching this line.\n"; 

    // ... recv(), select(), recv(), select(), etc in a loop until I have all the data 
    // send() a response to the client 
} while(dataReady > 0); 

我開始了與所有這一切都在一個大,難以讀取功能,和它的工作。然後我把它分解成一個獨立的類,與accept()的聯繫,現在它的行爲是不同的。用戶發送的第一個數據集正常。但客戶端等待來自服務器的響應,然後將第二組數據發送到套接字。但是,客戶端發送第二組數據後,select()不會返回;它阻塞,直到它超時。

我已經認定客戶是問題所在;數據包會在適當的時候正常發送。我也嘗試打印套接字文件描述符來證明它不會在某處發生更改。有誰知道爲什麼這段代碼可能不起作用嗎?可能導致select()阻止的因素有哪些?

編輯:它看起來像我的代碼運行在32位機器很好,但未能在64位機器。我仍然沒有解決這個問題,但是這個問題縮小了一點。

+1

像某人的聲音正在破壞'socket'變量。嘗試使用strace(1)運行服務器,以確保選擇和recv的所有參數都符合您的期望。或者單步調試器中的服務器,檢查系統調用參數 –

回答

3

如果沒有看到完整的代碼,很難說出可能的錯誤。但是,select()函數修改了傳遞給它的值fd_set。在調用select()之前,您需要確保重新初始化每個fd_set值,以便包含所需的套接字。

也要記住,recv()函數將阻塞,直到它得到一些數據(或關閉套接字)所以,除非你真的需要超時功能,你甚至可能不會需要調用select()。最後,recv()功能將返回,如果任何數據可用,不一定所有你所要求的。您將不得不在循環中重複呼叫recv()以獲取所有數據。 即使讀取少量字節,情況也是如此。

+0

是的,我知道。代碼本身非常長 - 我們正在談論數百行,其中大部分都是錯誤檢查。如果人們真的想要通過它,我可以發佈它。 雖然我在那裏重置fd_set值 - 就在我調用select之前,我總是調用FD_ZERO和FD_SET –