1. 程式人生 > >C# Socket連線請求超時機制

C# Socket連線請求超時機制

轉自:http://www.cnblogs.com/weidagang2046/archive/2009/02/07/1385977.html
作者:RazanPaul
譯者:Todd Wei
原文:http://www.codeproject.com/KB/IP/TimeOutSocket.aspx
介紹
您可能注意到了,.Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都沒有直接為Connect/BeginConnect提供超時控制機制。因此,當伺服器未處於監聽狀態,或者發生網路故障時,客戶端連線請求會被迫等待很長一段時間,直到丟擲異常。預設的等待時間長達20~30s。.Net Socket庫的SocketOptionName.SendTimeout提供了控制傳送資料的超時時間,但並非本文討論的連線請求的超時時間。
背景

這個問題最初源於我的某個專案,在解決以後,我曾將關鍵程式碼發表在自己的部落格上。我注意到不少人對此表示感謝,所以我想這是一個常見的問題,或許很多人都需要解決它。
實現
下面是實現的關鍵程式碼:

[csharp] view plaincopyprint?
  1. class TimeOutSocket  
  2. {  
  3.     privatestaticbool IsConnectionSuccessful= false;  
  4.     privatestatic Exception socketexception;  
  5.     privatestatic ManualResetEvent TimeoutObject= 
    new ManualResetEvent(false);  
  6.     publicstatic TcpClient Connect(IPEndPoint remoteEndPoint,int timeoutMSec)  
  7.     {  
  8.         TimeoutObject.Reset();  
  9.         socketexception = null;  
  10.         string serverip= Convert.ToString(remoteEndPoint.Address);  
  11.         int serverport= remoteEndPoint.Port;            
  12.         TcpClient tcpclient = new TcpClient();  
  13.         tcpclient.BeginConnect(serverip, serverport,  
  14.             new AsyncCallback(CallBackMethod), tcpclient);  
  15.         if (TimeoutObject.WaitOne(timeoutMSec,false))  
  16.         {  
  17.             if (IsConnectionSuccessful)  
  18.             {  
  19.                 return tcpclient;  
  20.             }  
  21.             else
  22.             {  
  23.                 throw socketexception;  
  24.             }  
  25.         }  
  26.         else
  27.         {  
  28.             tcpclient.Close();  
  29.             thrownew TimeoutException("TimeOut Exception");  
  30.         }  
  31.     }  
  32.     privatestaticvoid CallBackMethod(IAsyncResult asyncresult)  
  33.     {  
  34.         try
  35.         {  
  36.             IsConnectionSuccessful = false;  
  37.             TcpClient tcpclient = asyncresult.AsyncStateas TcpClient;  
  38.             if (tcpclient.Client!= null)  
  39.             {  
  40.                 tcpclient.EndConnect(asyncresult);  
  41.                 IsConnectionSuccessful = true;  
  42.             }  
  43.         }  
  44.         catch (Exception ex)  
  45.         {  
  46.             IsConnectionSuccessful = false;  
  47.             socketexception = ex;  
  48.         }  
  49.         finally
  50.         {  
  51.             TimeoutObject.Set();  
  52.         }  
  53.     }  
  54. }  
這裡,ManualResetEvent的WaitOne(TimeSpan, Boolean)起到了主要的作用。它將阻止當前執行緒,直到ManualResetEvent物件被Set或者超過timeout時間。上面的程式碼中,呼叫BeginConnect後通過WaitOne方法阻止當前執行緒,如果在timeoutMSec時間內連線成功,將在CallBackMethod回撥中呼叫TimeoutObject.Set,解除被阻塞的連線執行緒並返回;否則,連線執行緒會在等待超時後,主動關閉連線並丟擲TimeoutException。
總結
雖然實現非常簡單,但或許很多人都需要連線請求超時機制,如果有任何問題,我會盡力為您解答。
[譯註]
作者介紹了一種非同步連線+WaitOne的連線請求超時機制。其中的實現細節有值得商榷的地方,比如:a.static成員帶來的執行緒安全性問題;b.可以考慮利用IAsyncResult.AsyncWaitHandle,不必另行建立ManualResetEvent。但瑕不掩瑜,感謝作者的解決思路。

------------------------gdjlc備註-----------------------------------------
如果不用TcpClient,直接用Socket,可改為:
[csharp] view plaincopyprint?
  1. class TimeOutSocket  
  2.        {  
  3.            privatestaticbool IsConnectionSuccessful = false;  
  4.            privatestatic Exception socketexception;  
  5.            privatestatic System.Threading.ManualResetEvent TimeoutObject = new System.Threading.ManualResetEvent(false);  
  6.            publicstatic Socket Connect(IPEndPoint remoteEndPoint, int timeoutMSec)  
  7.            {  
  8.                TimeoutObject.Reset();  
  9.                socketexception = null;       
  10.                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
  11.                socketClient.BeginConnect(remoteEndPoint, new AsyncCallback(CallBackMethod), socketClient);  
  12.                if (TimeoutObject.WaitOne(timeoutMSec, false))  
  13.                {  
  14.                    if (IsConnectionSuccessful)  
  15.                        return socketClient;  
  16.                    else
  17.                        throw socketexception;                       
  18.                }  
  19.                else
  20.                {  
  21.                    socketClient.Close();  
  22.                    thrownew TimeoutException("TimeOut Exception");                      
  23.                }  
  24.            }  
  25.            privatestaticvoid CallBackMethod(IAsyncResult asyncresult)  
  26.            {  
  27.                try
  28.                {  
  29.                    IsConnectionSuccessful = false;  
  30.                    Socket socketClient = asyncresult.AsyncState as Socket;  
  31.                    if (socketClient != null)  
  32.                    {  
  33.                        socketClient.EndConnect(asyncresult);  
  34.                        IsConnectionSuccessful = true;  
  35.                    }  
  36.                }  
  37.                catch (Exception ex)  
  38.                {  
  39.                    IsConnectionSuccessful = false;  
  40.                    socketexception = ex;  
  41.                }  
  42.                finally
  43.                {  
  44.                    TimeoutObject.Set();  
  45.                }  
  46.            }  
  47.        }  

相關推薦

C# Socket連線請求超時機制

轉自:http://www.cnblogs.com/weidagang2046/archive/2009/02/07/1385977.html 作者:RazanPaul 譯者:Todd Wei 原文:http://www.codeproject.com/KB/IP/Time

C# Socket.Connect連線請求超時機制

作者:RazanPaul 譯者:Todd Wei 原文:http://www.codeproject.com/KB/IP/TimeOutSocket.aspx 轉自:http://hi.baidu.com/wf_studio/blog/item/d0a339f4c70c9a

C 中設定Socket連線請求超時

                C#中, 對於Socket的請求,無論是同步還是非同步,都沒有提供超時機制,SendTimeout,ReceiveTimeout均無用..對於需要測試網路是否正常連線的情況下,,超時控制很是有用,  如果伺服器不存在,或是客戶機網路異常,, 在沒有設定超時的情況下,,Socke

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

C#中, 對於Socket的請求,無論是同步還是非同步,都沒有提供超時機制,SendTimeout,ReceiveTimeout均無用.. 對於需要測試網路是否正常連線的情況下,,超時控制很是有用,  如果伺服器不存在,或是客戶機網路異常,, 在沒有設定超時的情況下,,So

C socket: 關於connect超時設定

使用阻塞的socket, 可以設定讀寫超時, struct timeval tv_timeout; tv_timeout.tv_sec = 60; tv_timeout.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_S

C# socket連線斷開問題

這一篇文章,我將圖文並茂地介紹Socket程式設計的基礎知識,我相信,如果你按照步驟做完實驗,一定可以對Socket程式設計有更好地理解。 第一步:建立解決方案 第二步:建立服務端程式 這裡可以選擇“Console Application”這個型別,比較方便除錯 然後編寫如下程式碼,實現伺服器的基本

socket連線及傳輸機制

連線: 1、service:socket--bind--listen--accept--write或read--close 2、client:scoket--connect--write或read--close 三次握手發生在服務端的listen,客戶端的connect,客

c#關於socket連線超時控制的方案

之前有一個專案用到Remoting技術,當遠端的地址無效或伺服器沒執行時,訪問遠端物件方法,會經過幾十秒的時間才丟擲異常。因為我用的是tcp模式,所以想到可以用socket來測試連線,就可以在呼叫遠端物件方法之前知道遠端服務有沒有執行。程式碼如下: public clas

C# 中使用TCP連線設定超時問題

在使用C#中用TCP連線去掃描IP的過程中,發現,TCP連線沒有可以設定連線超時的方法,如果掃描到空的IP或連線失敗,那要等20多秒,甚至更長, 我們可以重新去用Thread的join這個帶引數的執行緒,來解決這個問題,下面的這個類就是但連線超時引數的TCPCliento類 the TcpC

JavaWeb問題集錦: 資料庫連線請求超時 HikariPool-1 - Connection is not available, request timed out after 30000ms

報錯日誌:     java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30

Socket 關於設定Socket連線超時時間

做網路程式設計的人對setSoTimeout方法一定很熟悉,都知道是設定連線的超時時間! 但是我在網上找資料時發現很多人把這個超時時間理解成了鏈路的超時時間!我看了一下JDK 關於這個方法的說明,其實根本不是鏈路的超時時間! Java程式碼   setSoTimeout   public vo

連線 、短連線、心跳機制與斷線重連(轉載) Socket的長連線和短連線

概述 可承遇到,不知什麼原因,一個夜晚,機房中,大片的遠端呼叫連線斷開。 第二天早上,使用者訪問高峰,大部分伺服器都在獲取連線,造成大片網路阻塞。 服務崩潰,慘不忍睹的景象。 本文將從長連線和短連線的概念切入,再到長連線與短連線的區別,以及應用場景,引出心跳機制和斷線重連,給出程式碼實現。 從原

c# https get請求 基礎連線已關閉,接受時發生錯誤 解決方法

用HttpWebRequest模擬傳送https請求,提示錯誤: 基礎連線已關閉,接受時發生錯誤在本地測試ok,開發環境為64位win7 vs2013 釋出到windows server 2008 x86系統上執行一直報錯。。下載2008 r2 x64執行發現數據正常。。pu

C socket 傳送HTTP請求

HTTP請求頭部樣例: GET http://www.baidu.com/ HTTP/1.1 Accept: html/text Host: 220.181.6.175:80 Connection: Close 這是一個請求百度頁面的頭部。 屬性和值的命名中間用:和空格隔

Socket的讀取超時連線超時

catch (SocketTimeoutException e) {        e.printStackTrace();        Log.i("xfh", "getIp...SocketTimeoutException");        if (!socket.isClosed() &&a

C#中Socket.Receive()的超時問題

最近在除錯程式的時候,希望1秒鐘呼叫一次 Socket.Receive() 來接收資料。 實際上,應該是說,如果沒有資料到來,就是1秒鐘一次,如果有資料到來,則收到資料後立即繼續接收,然後繼續是1秒鐘接收一次。 C#的相關程式碼如下: public boo

C++ socket中recv和send機制

利用TCP傳遞資訊時要注意:TCP傳輸是流的方式:即send 100個位元組後對方如果沒有及時recv取出, 這時又send 100個位元組,則recv有可能接收到兩次傳送疊加的部分或全部資料,所有在傳送結構體資料 時,應當傳送以後睡眠一段時間,使對方recv有足夠的實際取

Linux下Socket連線超時的一種實現方法

目前各平臺通用的設定套接字(Socket)連線超時的辦法是: 建立套接字,將其設定成非阻塞狀態。呼叫connect連線對端主機,如果失敗,判斷當時的errno是否為EINPROGRESS,也就是說是不是連線正在進行中,如果是,轉到步驟3,如果不是,返回錯誤。用select在指定的超時時間內監聽套接字的寫就

C++socket客戶端select非同步連線傳送接收資料

這段時間公司專案一直用網口同底層裝置互動,顧記錄下,具體見程式碼: int RFID_STANDARDPROTOCOL_API __stdcall Socket_SendAndRecv(SOCKET Socket, unsigned char * SendBuf

c++ socket 編程步驟

socket 編程 客戶機 connect 服務器 nbsp listen 步驟 ket sock 服務器 socket() bind() listen()                   客戶機 accept()