2012-08-06 141 views
9

我正在處理一個客戶端/服務器關係,這意味着無限量的時間來回推送數據。如何檢測C中的套接字斷開連接#

我試圖克服的問題是在客戶端,是我無法設法找到一種方法來檢測斷開連接。

我從其他人的解決方案中取得了一些通行證,從捕獲IO異常到輪詢所有三個SelectMode上的套接字。我也嘗試過使用輪詢的組合,並在套接字的'可用'字段中進行檢查。

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 
     bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead); 
     bool part2 = (this.Connection.Client.Available == 0); 

     if (part1 & part2) 
     { 
      // Never Occurs 
      //connection is closed 
      return false; 
     } 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never Occurs Either 
    } 
} 

在服務器端,寫一個「空」字符的嘗試(\ 0)到客戶端強制IO異常和服務器可以檢測該客戶端已經斷開(相當容易演出)。

在客戶端,同樣的操作不會產生異常。

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 

     this.WriteHandle.WriteLine("\0"); 
     this.WriteHandle.Flush(); 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never occurs 
     this.OnClosed("Yo socket sux"); 
     return false; 
    } 
} 

,我相信我在通過調查檢測斷開有一個問題,就是我可以很容易遇到一個錯誤上SelectRead,如果我的服務器還沒有,因爲寫東西回客戶端最後一次檢查...不知道該怎麼做,我已經追逐了每一個選項,使我能夠找到這個檢測,並且對我來說什麼都沒有100%,最終我的目標是檢測服務器(或連接)失敗,通知客戶,等待重新連接等。所以我相信你可以想象這是一個不可或缺的部分。

欣賞任何人的建議。 提前致謝。

編輯:任何查看此問題的人都應該注意下面的答案以及我的最終評論。我詳細闡述了我如何克服這個問題,但還沒有製作'Q &'風格的帖子。

+0

只需捕獲IOExceptions並使用讀取超時。你不需要所有這些其他的malarkey。 – EJP 2012-08-06 23:23:09

+0

我已經嘗試過(因爲你沒有真正閱讀我的帖子...),它的命中或錯過。讀操作超時後會導致IO,這會強制斷開連接......但是如果我只是沒有收到數據......? – DigitalJedi805 2012-08-07 01:37:59

+0

我閱讀了你的文章。它不是'碰撞和錯過',它受到本地和遠程異步數據緩衝的影響。在第一次寫入失敗的連接時,您將不會收到異常,因爲它尚未被檢測到:在TCP重新嘗試超時後,您將在後續寫入時獲取它。 – EJP 2012-08-07 04:34:11

回答

12

一個選項是使用TCP保持活動數據包。您打電話給Socket.IOControl()。只有惱人的一點是,它需要一個字節數組作爲輸入,所以你必須將數據轉換爲字節數組通過在這裏的使用10000ms一個例子保持活動與1000毫秒重試:

Socket socket; //Make a good socket before calling the rest of the code. 
int size = sizeof(UInt32); 
UInt32 on = 1; 
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds. 
UInt32 retryInterval = 1000; //If no response, resend every second. 
byte[] inArray = new byte[size * 3]; 
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size); 
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size); 
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size); 
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null); 

保持只有當您沒有發送其他數據時纔會發送活動數據包,因此每次發送數據時,10000ms定時器都將被複位。

+0

太棒了,謝謝喬爾,我一打開我的開發系統就一定會給我一個旋轉。 – DigitalJedi805 2012-08-07 01:38:41

+0

嘿喬爾,所以我想我在這裏得到的主意,但請糾正我,如果我是錯的; IOControl方法在套接字上定時傳遞'KeepAlive'數據包。我(幾乎一字不差)將上面的代碼添加到了我的SocketServer.Client和SocketClient構造函數中。我把計時器減少到一秒鐘(因爲這是我雙方'讀'的超時?),但我的StreamReader.ReadLine(只是意識到我輸入這個,這應該是我的策略)從來沒有捕獲任何數據...我必須說我不確定我們爲什麼要把我們要放入陣列的東西放在一起;我可以線路終止它嗎? – DigitalJedi805 2012-08-07 16:10:02

+0

其實只是嘗試用StreamReader.Read調用運行相同的東西,並且從來沒有在任何方向上得到任何東西。可能是因爲我不完全理解這個概念。 – DigitalJedi805 2012-08-07 16:14:25