我试图在异步HTTP客户端中重用套接字,但我无法第二次连接到主机。我基本上把我的异步HTTP客户端状态机具有以下状态:重用异步套接字:后续连接尝试失败
- 可用:插座可供使用
- 连接:将插座连接到端点
- 发送:套接字发送数据到端点
- 接收:插座从端点
- 无法接收数据:有一个插座故障
- 清理:清理套接字状态
在连接状态下我打电话BeginConnect
:
private void BeginConnect()
{
lock (_sync) // re-entrant lock
{
IPAddress[] addersses = Dns.GetHostEntry(_asyncTask.Host).AddressList;
// Connect to any available address
IAsyncResult result = _reusableSocket.BeginConnect(addersses, _asyncTask.Port, new AsyncCallback(ConnectCallback), null);
}
}
回调方法改变状态Sending
一次成功的连接已经建立:
private void ConnectCallback(IAsyncResult result)
{
lock (_sync) // re-entrant lock
{
try
{
_reusableSocket.EndConnect(result);
ChangeState(EClientState.Sending);
}
catch (SocketException e)
{
Console.WriteLine("Can't connect to: " + _asyncTask.Host);
Console.WriteLine("SocketException: {0} Error Code: {1}", e.Message, e.NativeErrorCode);
ThreadPool.QueueUserWorkItem(o =>
{
// An attempt was made to get the page so perform a callback
ChangeState(EClientState.Failed);
});
}
}
}
在我Shutdown
的清理插座和Disconnect
带重用标记:
后续调用BeginConnect
结果和例外:
SocketException:连接尝试 失败,因为连接的方没有 一段 时间后没有正确答复或建立的连接失败 因为连接主机未能响应 XX.XXX.XX.XX:80
错误代码:10060
下面是状态跟踪:
Initializing...
Change State: Connecting
Change State: Sending
Change State: Receiving
Change State: CleanUp
Callback: Received data from client 0 // <--- Received the first data
Change State: Available
Change State: Connecting // <--- Timeout when I try to reuse the socket to connect to a different endpoint
什么我必须做的,以便能够重新使用套接字连接到不同的主机?
注意:我有
而不是
试图重新连接到同一主机,但
我假设
发生同样的事情(即无法连接)。
更新
我发现下面的音符在documentation of BeginConnect:
如果此套接字之前已断开连接,然后BeginConnect必须在一个线程,将不会退出,直到操作完成调用。这是底层提供商的限制。此外,使用的EndPoint必须不同。
我开始怀疑我的问题是否与该问题有关...我正在连接到不同的EndPoint,但它们是什么意思,我们称之为BeginConnect的线程在操作完成之前不能退出?
更新2.0:
我问了related question,我尝试使用“异步家庭”调用,而不是“开始家庭”电话,但我得到了同样的问题!
我不知道为什么我没有回答你的问题,但我做这种微型优化的原因是因为我每秒抓取300多个网页,每次抓取都要求我关闭旧套接字,处置它并打开一个新套接字。该应用程序运行时间很长,因此最终会导致内存抖动并降低系统速度。性能是这种情况下的关键。 – Kiril 2011-11-24 06:24:44