TcpClient.Connect函数连接超时的问题
问题原述:
/t/0616/15/4825920.html
调用TcpClient.Connect函数连接其他机器。我在一台机器上测试程序,对于连接根本无法连接(物理连接不通)的机器,该函数用时5秒左右返回,并捕获SocketException异常。我在另一台机器上测试时,Connect函数用时26秒左右的时间才返回。请问有没有方法设置Connect函数连接超时的时间,如果超过一定时间还没有连上则返回。
解决方法:
写了个帮助类,用了线程池
class TcpClientConnector
{
/// <summary>
/// 在指定时间内尝试连接指定主机上的指定端口。
/// </summary>
/// <param name="hostname">要连接到的远程主机的 DNS 名。</param>
/// <param name="port">要连接到的远程主机的端口号。</param>
/// <param name="millisecondsTimeout">要等待的毫秒数,或 -1 表示无限期等待。</param>
/// <returns>已连接的一个 TcpClient 实例。</returns>
/// <remarks>本方法可能抛出的异常与 TcpClient 的构造函数重载之一
/// public TcpClient(string, int) 相同,并若指定的等待时间是个负数且不等于
/// -1,将会抛出 ArgumentOutOfRangeException。</remarks>
public static TcpClient Connect(string hostname, int port, int millisecondsTimeout)
{
ConnectorState cs = new ConnectorState();
cs.Hostname = hostname;
cs.Port = port;
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectThreaded), cs);
if (pleted.WaitOne(millisecondsTimeout, false))
{
if (cs.TcpClient != null) return cs.TcpClient;
throw cs.Exception;
}
else
{
cs.Abort();
throw new SocketException(11001); // cannot connect
}
}
private static void ConnectThreaded(object state)
{
ConnectorState cs = (ConnectorState)state;
cs.Thread = Thread.CurrentThread;
try
{
TcpClient tc = new TcpClient(cs.Hostname, cs.Port);
if (cs.Aborted)
{
try { tc.GetStream().Close(); }
catch { }
try { tc.Close(); }
catch { }
}
else
{
cs.TcpClient = tc;
pleted.Set();
}
}
catch (Exception e)
{
cs.Exception = e;
pleted.Set();
}
}
private class ConnectorState
{
public string Hostname;
public int Port;
public volatile Thread Thread;
public readonly ManualResetEvent Completed = new ManualResetEvent(false);
public volatile TcpClient TcpClient;
public volatile Exception Exception;
public volatile bool Aborted;
public void Abort()
{
if (Aborted != true)
{
Aborted = true;
try { Thread.Abort(); }
catch { }
}
}
}
}
=================================
用法示例:
try
{
Console.WriteLine("Connecting to nonexistenthost...");
TcpClient tc = TcpClientConnector.Connect("nonexistent", 80, 1000);
Console.WriteLine("Returned");
try { tc.GetStream().Close(); }
catch { }
try { tc.Close(); }
catch { }
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}