1. 程式人生 > >客戶端怎麼判斷Socket連線已與伺服器斷開

客戶端怎麼判斷Socket連線已與伺服器斷開

First of all , Server's socekt is not close.
if u had closed client's socekt , u should creat it again when u want to connect server's.

socket即使close了,也還是會存在的,除非設定socket的option,設定為立即close
看一下setsockopt()這個函式吧

附一朋友的問題:

伺服器程式為Socket   Sever,繫結12005埠,啟動就Listen,然後客戶端不停的連線、斷開,在每天4點伺服器程式自動關閉後,又由另外一個守候程式開啟。伺服器執行8-9天后,客戶端不能連線了,連線的客戶端也請求不了資料,就是說伺服器程式不接受SOCKET連線了,傳送的資料在OnReceive()不能接受了,在這個時間用遠端登入可以登入到伺服器,CPU也是4%左右,自己的伺服器程式用記憶體也是不到10M(曾經到過70M也沒問題),資料的一條線城也沒有堵塞(當時自己開啟SQL2000企業管理器檢視到的),關閉自己伺服器程式,客戶端又可以連線上來,但是過了2個小時又是上面的情況,這次關閉自己伺服器程式也不能連線了,只好將作業系統關閉,重新啟動伺服器機器,重起後可以了。  
   
  又要執行到8-9天后才發生重複的事情、、、,好奇怪呀,已經連續發生4次了,找不到原因,  
   
  自己認為  
  1、是不是作業系統的埠8-9天后用完了?如果是  
  2、記憶體用完了?(1G系統記憶體,在資源管理器看到是一直穩定到830M左右)  

---------------------------------------------------------------------------------------------------

TCP連線如果不收發資料,大約幾十秒之後就會超時,超時之後伺服器端不會收到OnClose()  
  這樣一來,就會有許多死連線,伺服器端無法清除。  
b/S之間沒有資料傳送的時候要傳送一些線上包,比如說,沒有資料傳輸時每20秒傳送一個空格  
  Server端對每個連線定時檢測,大概象下面這樣:  
  OnRecv()  
  {  
    last_recv_time   =   GetTickCount();  
    //do   recv()   here  
  }  
   
  OnTimer()  
  {  
    if(GetTickCount()-last_recv_time>35000)//close   connection   any   way   after   35   seconds'   idle  
    {  
      closesocket(s)  
    }  
  }

客戶端要有重連機制

C#中判斷socket是否已斷開的方法

在C#中,Socket類的Connected屬性只表示最後一次I/O操作的狀態,如果這之後[連線的另一方]斷開了,它還一直返回true, 除非你再通過socket來發送資料。所以通過這個屬性來判斷是行不通的!
       有人說可以用Socket.Available屬性來判斷,msdn中說:如果[連線的另一方]斷開了,它就會丟擲異常。然而,這個BUG報告(http://dam.mellis.org/2004/08/net_socket_bugs_gotchas/)卻指出:msdn的說法並不完全正確,這個屬性只有在少數情況下才丟擲異常。所以,這一招還是行不通!
       事實上,Socket.Receive()方法在[連線的另一方]斷開時,它返回結果告知只讀了0個位元組,我們可以籍由這一點來找出答案。這個問答(

http://www.dotnet247.com/247reference/msgs/36/182526.aspx)給出了好的解決方案:可以呼叫Socket.Poll() 方法,為該方法的第二個引數傳入SelectRead 值,如果該方法返回true, 則可以再由Socket.Receive()方法的返回值來判斷, 我簡要的寫出程式碼:
         Socket s = new Socket(..);
if (s.Poll(-1, SelectMode.SelectRead))
{
   int nRead = s.Receive();
   if (nRead == 0)
   {
     //socket連線已斷開
    }
}     
       如果您還有更好的方法,也請告訴我, :).