C# 中使用TCP連線設定超時問題
阿新 • • 發佈:2018-11-03
在使用C#中用TCP連線去掃描IP的過程中,發現,TCP連線沒有可以設定連線超時的方法,如果掃描到空的IP或連線失敗,那要等20多秒,甚至更長,
我們可以重新去用Thread的join這個帶引數的執行緒,來解決這個問題,下面的這個類就是但連線超時引數的TCPCliento類
the TcpClientWithTimeout.cs class:
using System; using System.Net.Sockets; using System.Threading; /// <summary> /// TcpClientWithTimeout 用來設定一個帶連線超時功能的類 /// 使用者可以設定毫秒級的等待超時時間 (1000=1second) /// 例如: /// TcpClient connection = new TcpClientWithTimeout('127.0.0.1',80,1000).Connect(); ///iP,埠,超時時間 /// </summary> public class TcpClientWithTimeout { protected string _hostname; protected int _port; protected int _timeout_milliseconds; protected TcpClient connection; protected bool connected; protected Exception exception; public TcpClientWithTimeout(string hostname,int port,int timeout_milliseconds) { _hostname = hostname; _port = port; _timeout_milliseconds = timeout_milliseconds; } public TcpClient Connect() { //建立一個執行緒去做TCP連線 connected = false; exception = null; Thread thread = new Thread(new ThreadStart(BeginConnect)); thread.IsBackground = true; // 作為後臺執行緒處理 // 不會佔用機器太長的時間 thread.Start(); // 等待如下的時間,JOIN阻塞執行緒一個等待時間,,阻塞後,如果連線成功,則返回這個connect物件,如果連線是失敗的,結束這個tcp連線的執行緒,這裡是關鍵,這樣就實現了一個帶有超時功能 的TCP連線類 thread.Join(_timeout_milliseconds); if (connected == true) { // 如果成功就返回TcpClient物件 thread.Abort(); return connection; } if (exception != null) { // 如果失敗就丟擲錯誤 thread.Abort(); throw exception; } else { // 同樣地丟擲錯誤 thread.Abort(); string message = string.Format("TcpClient connection to {0}:{1} timed out", _hostname, _port); throw new TimeoutException(message); } } protected void BeginConnect() { try { connection = new TcpClient(_hostname, _port); // 標記成功,返回呼叫者 connected = true; } catch (Exception ex) { // 標記失敗 exception = ex; } } } 下面的這個例子就是如何利用5秒的超時,去連線一個網站傳送10位元組的資料,並且接收10位元組的資料。 // 設定一個帶有5秒超時的tcp連線 TcpClient connection = new TcpClientWithTimeout("www.google.com", 80, 5000).Connect(); NetworkStream stream = connection.GetStream(); // 傳送10位元組 byte[] to_send = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa}; stream.Write(to_send, 0, to_send.Length); //接收10位元組 byte[] readbuf = new byte[10]; // you must allocate space first stream.ReadTimeout = 10000; // 10 second timeout on the read stream.Read(readbuf, 0, 10); // read // 關閉連線 stream.Close(); // workaround for a .net bug: http://support.microsoft.com/kb/821625 connection.Close();