TcpClient.Connect函数连接超时的问题

liudaqin 2006-06-16 03:55:59
调用TcpClient.Connect函数连接其他机器。我在一台机器上测试程序,对于连接根本无法连接(物理连接不通)的机器,该函数用时5秒左右返回,并捕获SocketException异常。我在另一台机器上测试时,Connect函数用时26秒左右的时间才返回。请问有没有方法设置Connect函数连接超时的时间,如果超过一定时间还没有连上则返回。致谢。
...全文
2497 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
liudaqin 2006-08-02
  • 打赏
  • 举报
回复
多谢
lj915 2006-07-25
  • 打赏
  • 举报
回复
帮顶!
netmicro 2006-07-25
  • 打赏
  • 举报
回复
写了个帮助类,用了线程池

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 (cs.Completed.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;
cs.Completed.Set();
}
}
catch (Exception e)
{
cs.Exception = e;
cs.Completed.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);
}
liudaqin 2006-06-20
  • 打赏
  • 举报
回复
还有没有其他的解决办法,敬请赐教,致谢。
Knight94 2006-06-19
  • 打赏
  • 举报
回复
如果还不行,你就继承TcpClient,然后设置其保护成员Client,即个socket对象,看看是否能通过“Socket.SetSocketOption”来进行设置。

不过.net在这里封得比较死
Knight94 2006-06-19
  • 打赏
  • 举报
回复
如果这两个参数不管用的话,你可以试试把NoDelay设为true。

liudaqin 2006-06-19
  • 打赏
  • 举报
回复
老兄,真的不行。
我不设置SendTimeout和ReceiveTimeout,在我的机器上测试也是耗时6秒左右。
设置SendTimeout和ReceiveTimeout为3000后在实验室测试依然是耗时26秒左右。
下面是禁用北渐站、东滩站和南屯站的输出结果:
2006-6-19 11:16:08准备连接 北渐站
2006-6-19 11:16:34向北渐站连接失败,状态设为false,由于连接方在一段时间后没有正确的答复或连接的主机没有反应,连接尝试失败。 // 26秒才返回
2006-6-19 11:16:34准备连接 东滩站
2006-6-19 11:16:59向东滩站连接失败,状态设为false,由于连接方在一段时间后没有正确的答复或连接的主机没有反应,连接尝试失败。 // 25秒才返回
2006-6-19 11:16:59准备连接 南屯站
2006-6-19 11:17:25向南屯站连接失败,状态设为false,由于连接方在一段时间后没有正确的答复或连接的主机没有反应,连接尝试失败。 // 26秒才返回
2006-6-19 11:17:25准备连接 鲍店站
2006-6-19 11:17:26向鲍店站连接失败,状态设为false,不能做任何连接,因为目标机器积极地拒绝它。

下面是只禁用北渐站输出结果:
2006-6-19 11:19:16准备连接 北渐站
2006-6-19 11:19:42向北渐站连接失败,状态设为false,由于连接方在一段时间后没有正确的答复或连接的主机没有反应,连接尝试失败。 // 26秒才返回
2006-6-19 11:19:42准备连接 东滩站
2006-6-19 11:19:43向东滩站连接失败,状态设为false,不能做任何连接,因为目标机器积极地拒绝它。
2006-6-19 11:19:43准备连接 南屯站
2006-6-19 11:19:44向南屯站连接失败,状态设为false,不能做任何连接,因为目标机器积极地拒绝它。
2006-6-19 11:19:44准备连接 鲍店站
2006-6-19 11:19:45向鲍店站连接失败,状态设为false,不能做任何连接,因为目标机器积极地拒绝它。

敬请赐教,致谢。

iegrhn 2006-06-19
  • 打赏
  • 举报
回复
Knight94 2006-06-19
  • 打赏
  • 举报
回复
to 没有用,我设置SendTimeout和ReceiveTimeout均为3000,但是在连接的时候还是用掉了6秒。

没错啊, 3+3等于6
liudaqin 2006-06-19
  • 打赏
  • 举报
回复
没有用,我设置SendTimeout和ReceiveTimeout均为3000,但是在连接的时候还是用掉了6秒。
liudaqin 2006-06-19
  • 打赏
  • 举报
回复
to liangxf0022

你的这个方法确实可以用,但是如果对方机器打开了防火墙,并且禁止ping入的话,这种方法就失效了。
liudaqin 2006-06-19
  • 打赏
  • 举报
回复
to Knight94(愚翁)

1.把NoDelay设为true不行。
2.继承TcpClient,通过设置Socket.SetSocketOption也不行。
liangxf0022 2006-06-19
  • 打赏
  • 举报
回复
我们原来的项目是通过执行ping命令检查,然后再连接
liangxf0022 2006-06-19
  • 打赏
  • 举报
回复
你可以设置TcpClient的SendTimeout以及ReceiveTimeout试试。

这2个参数是控制发送和接收消耗的时间,不是控制连接消耗的时间。
Knight94 2006-06-16
  • 打赏
  • 举报
回复
你可以设置TcpClient的SendTimeout以及ReceiveTimeout试试。

110,580

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧