1. 程式人生 > >C 中設定Socket連線請求的超時

C 中設定Socket連線請求的超時

               

C#中, 對於Socket的請求,無論是同步還是非同步,都沒有提供超時機制,SendTimeout,ReceiveTimeout均無用..

對於需要測試網路是否正常連線的情況下,,超時控制很是有用,  如果伺服器不存在,或是客戶機網路異常,, 在沒有設定超時的情況下,,Socket請求

需要等很久...

於是找呀找,,終於在網上找到解決的辦法,  程式碼如下...

[csharp] view plain copy print?
  1. <code class="language-csharp"privatereadonly ManualResetEvent TimeoutObject = new
     ManualResetEvent(false);  
  2.         /// <summary> 
  3.         /// Socket連線請求       
  4.         /// </summary>     
  5.         ///<param name="remoteEndPoint">網路端點</param>      
  6.         ///<param name="timeoutMSec">超時時間</param> 
  7.         publicvoid Connect(IPEndPoint remoteEndPoint, int timeoutMSec)  
  8.         {  
  9.             TimeoutObject.Reset();  
  10.             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
  11.             socket.BeginConnect(remoteEndPoint, CallBackMethod, socket);  
  12.             //阻塞當前執行緒           
  13.             if (TimeoutObject.WaitOne(timeoutMSec, 
    false))  
  14.             {   
  15.                 //MessageBox.Show("網路正常");
  16.             }  
  17.             else
  18.             {   
  19.                 //MessageBox.Show("連線超時");
  20.             }  
  21.         }  
  22.         //--非同步回撥方法       
  23.         privatevoid CallBackMethod(IAsyncResult asyncresult)  
  24.         {  
  25.             //使阻塞的執行緒繼續        
  26.             TimeoutObject.Set();  
  27.         }</code>  
 private readonly ManualResetEvent TimeoutObject = new ManualResetEvent(false);        /// <summary>         /// Socket連線請求               /// </summary>             ///<param name="remoteEndPoint">網路端點</param>              ///<param name="timeoutMSec">超時時間</param>         public void Connect(IPEndPoint remoteEndPoint, int timeoutMSec)        {            TimeoutObject.Reset();            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            socket.BeginConnect(remoteEndPoint, CallBackMethod, socket);            //阻塞當前執行緒                       if (TimeoutObject.WaitOne(timeoutMSec, false))            {                 //MessageBox.Show("網路正常");            }            else            {                 //MessageBox.Show("連線超時");            }        }        //--非同步回撥方法               private void CallBackMethod(IAsyncResult asyncresult)        {            //使阻塞的執行緒繼續                    TimeoutObject.Set();        }

程式碼雖然簡單,不過其思路還是不錯的,大概說一下其原理:

重點就是TimeoutObject.WaitOne與Socket的BeginConnect非同步請求的回撥函式CallBackMethod.!

首先利用TimeoutObject.WaitOne阻塞當前執行緒,並設定等待時間,,如果在等待的時間內仍然無訊號,則判斷為連線超時,

在網路正常連線的情況下,通過Socket的BeginConnect非同步請求,伺服器正常回應,則會呼叫CallBackMethod回撥函式,關鍵就在這裡了,我們在CallBackMethod函式中,給予TimeoutObject訊號,TimeoutObject在指定時間timeoutMSec內收到訊號,WaitOne返回True,則認為網路連線正常..

如果網路異常,,CallBackMethod函式得不到呼叫,TimeoutObject則一直處於等待狀態,超過指定的時間.,WaitOne不再繼續等待,直接返回False,則認為網路連線超時..