2011-08-29 46 views
1

我在Unix上有一個基於telnet的服務器的間歇性問題(這個問題在AIX和Linux上都出現了)。 服務器打開兩個套接字,一個連接到客戶端telnet會話,另一個連接到與服務器在同一臺計算機上運行的程序。這個想法是數據通過服務器傳遞給這個程序和從這個程序傳遞過來。選擇和讀取套接字(Unix)

當前設置有一個循環,使用select等待「讀取」文件描述符變爲可用,然後使用select等待「寫入」文件描述符變爲可用。

然後程序從傳入的文件描述符中讀取數據,然後在寫入輸出描述符之前處理數據。

下面的代碼片段顯示了發生了什麼。問題在於偶爾讀取失敗,並將errno設置爲ECONNRESET或ETIMEDOUT。這些都不是通過閱讀記錄的代碼,所以它們來自哪裏?

真正的問題是,我該如何阻止這種情況發生,或者優雅地處理它? 可以做兩個連續的選擇是問題嗎?

當前的處理行爲是關閉並重新啓動。需要注意的一點是,一旦發生這種情況,通常會發生三次或四次,然後清理。系統負載似乎不是那麼高(這是一個大的服務器)。

 if (select(8, &readset, NULL, NULL, NULL) < 0) 
       { 
       break; 
       } 
     if (select(8, NULL, &writeset, NULL, NULL) < 0) 
       { 
       break; 
       } 

     if (FD_ISSET(STDIN_FILENO, &readset) 
     && FD_ISSET(fdout, &writeset)) 
       { 
       if ((nread = read(STDIN_FILENO, buff, BUFFSIZE)) < 0) 
         { 
         /* This sometimes fails with errno = 
          ECONNRESET or ETIMEDOUT */ 
         break; 
         } 
       } 
+1

你知道,你可以將這兩個'select'調用合併爲一個。另外,'select'的第一個參數應該是set + 1中的最大fd,而不是8.同樣,stdin是套接字嗎? – Hasturkun

+0

返回ETIMEDOUT的STDIN_FILENO是不尋常的。你在做什麼特別的事情嗎? (重定向,fcntls等)? – cnicutar

+0

我建議你從實施Hasturkun的建議開始,如果處理不當,選擇可能會相當溫和。 – fvu

回答

0

查看第85和98行的http://lxr.free-electrons.com/source/arch/mips/include/asm/errno.h中的註釋:這些基本上說有網絡連接復位或超時。檢查並查看是否存在可以在遠程網絡程序上進行調整的超時,或者發送一些定期填充字節以確保連接一直保持清醒狀態。您可能只是遠程客戶端和本地服務器之間的網絡傳輸路徑中的錯誤的受害者(當我的DSL線路打嗝時,這發生在我身上)。

編輯:不知道downvote是什麼。 man page for read明確指出:

根據連接到fd的對象,可能會發生其他錯誤。

的錯誤可能是存在的在select,而不是在read:你select後不是在檢查錯誤,你只是在進行read,如果select返回一個錯誤,這將失敗。我打賭,如果您在select調用後檢查錯誤值,您將看到錯誤:您無需等待read查看錯誤。

+0

您可能會爲您的編輯獲得另一個-1,re:錯誤來自哪裏。一個失敗的'read'會覆蓋'errno' – Hasturkun

+0

我有理由相信它不是一個「真正的」超時,因爲它在連接時立即發生。 –

+0

各個第7章手冊頁記錄了讀取(和其他系統調用)可以在不同類型的套接字上返回的附加錯誤代碼。請參閱socket(7),ip(7),tcp(7)和/或unix(7)。請注意,select調用通常是WONT給你的錯誤代碼;它將返回成功,這意味着套接字上的讀取不會被阻止 –