C# 中使用TCP连接设置超时问题

在使用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();

猜你喜欢

转载自blog.csdn.net/zxhadolph/article/details/83514033