C# .NET套接字超时-关闭时阻塞方法
使用异步套接字调用实现连接超时时遇到问题 我的想法是在套接字对象上调用BeginConnect,然后在超时时间过后使用计时器调用套接字 只要在GUI线程上创建套接字,这就可以正常工作——Close方法立即返回,回调方法被执行。但是,如果套接字是在任何其他线程上创建的,则Close方法将阻塞,直到出现默认的IP超时 要复制的代码:C# .NET套接字超时-关闭时阻塞方法,c#,.net,sockets,C#,.net,Sockets,使用异步套接字调用实现连接超时时遇到问题 我的想法是在套接字对象上调用BeginConnect,然后在超时时间过后使用计时器调用套接字 只要在GUI线程上创建套接字,这就可以正常工作——Close方法立即返回,回调方法被执行。但是,如果套接字是在任何其他线程上创建的,则Close方法将阻塞,直到出现默认的IP超时 要复制的代码: private Socket client; private void button1_Click(object sender, EventArgs e) {
private Socket client;
private void button1_Click(object sender, EventArgs e) {
// Creating the socket on a threadpool thread causes Close to block.
ThreadPool.QueueUserWorkItem((object state) => {
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = client.BeginConnect(IPAddress.Parse("144.1.1.1"), 23, new AsyncCallback(CallbackMethod), client);
// Wait for 2 seconds before closing the socket.
if (result.AsyncWaitHandle.WaitOne(2000)) {
MessageBox.Show("Connected.");
} else {
MessageBox.Show("Timed out. Closing socket...");
client.Close();
MessageBox.Show("Socket closed.");
}
});
}
private void CallbackMethod(IAsyncResult result) {
MessageBox.Show("Callback started.");
Socket client = result.AsyncState as Socket;
try {
client.EndConnect(result);
} catch (ObjectDisposedException) {
}
MessageBox.Show("Callback finished.");
}
如果删除QueueUserWorkItem行,并在GUI线程上创建套接字,则套接字会立即关闭而不会阻塞
有人能解释一下发生了什么事吗?谢谢 编辑-系统.Net跟踪输出似乎有所不同,这取决于它是在GUI线程上连接还是在其他线程上连接:
我还尝试在常规线程(thread.Start())中运行套接字对象,而不是使用线程池。这样,您就可以保留对线程的引用,并自己调用thread.Interrupt()和/或thread.Abort()。关闭时的阻塞发生与MessageBox.Show无关。即使在超时为零的情况下将套接字的属性设置为true也无济于事。来自MSDN:“下表描述了Enabled属性和LingerState属性中存储的LingerTime属性的可能值的Close方法的行为。”当LingerState已启用且LingerTime设置为零时:“丢弃所有挂起的数据。对于面向连接的套接字(例如TCP),Winsock重置连接。”我尝试用上述程序重新编程。我无法重新编程。程序没有挂起。这在Windows 7和XP模式下的任何版本的.NET Framework上都会发生。我也可以在不同的机器上复制它。程序不应该挂起,但是在“超时。关闭套接字…”消息和“套接字关闭。”消息之间应该有大约20秒的延迟。尝试获取tracelog(请参阅),并将日志文件放在pastebin.com上。我可以看一下。谢谢你,我已经编辑了我的问题,包括跟踪日志。底层套接字调用似乎因调用它们的线程而异。在套接字连接之前调用Shutdown会导致SocketException-“发送或接收数据的请求被禁止,因为套接字未连接,并且(使用sendto调用在数据报套接字上发送时)未提供地址”。我目前正在使用一个线程启动多个BeginConnect,然后使用System.Timers.Timer根据需要超时套接字-我不能为每个连接使用新线程:(