【发布时间】:2011-04-23 04:57:14
【问题描述】:
我正在尝试在异步 HTTP 客户端中重用套接字,但第二次无法连接到主机。我基本上将我的异步 HTTP 客户端视为具有以下状态的状态机:
- Available:套接字可用
- 正在连接:套接字正在连接到端点
- 正在发送:套接字正在向端点发送数据
- 正在接收:套接字正在从端点接收数据
- 失败:出现套接字故障
- 清理:清理套接字状态
在连接状态我调用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 带有重用标志:
private void CleanUp()
{
lock (_sync) // re-entrant lock
{
// Perform cleanup
if (_reusableSocket.Connected)
{
_reusableSocket.Shutdown(SocketShutdown.Both);
_reusableSocket.Disconnect(true);
}
ChangeState(EClientState.Available);
}
}
对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,但它们意味着我们调用 BeginConnect 的线程在操作完成之前不能退出?
更新 2.0:
我问了related question,我尝试使用“Async family”调用而不是“Begin family”调用,但我遇到了同样的问题!!!
【问题讨论】:
标签: c# http sockets asynchronous httpclient