gpt4 book ai didi

c# - 重用异步套接字 : subsequent connect attempts fail

转载 作者:太空狗 更新时间:2023-10-29 20:37:42 26 4
gpt4 key购买 nike

我正在尝试在异步 HTTP 客户端中重用套接字,但我无法第二次连接到主机。我基本上将我的异步 HTTP 客户端视为具有以下状态的状态机:

  • Ava​​ilable:套接字可用
  • 正在连接:套接字正在连接到端点
  • 发送:套接字正在向端点发送数据
  • 正在接收:套接字正在从端点接收数据
  • 失败:套接字失败
  • Clean Up:清理套接字状态

在连接状态我调用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);
}
}

一旦成功建立连接,回调方法将状态更改为正在发送:

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);
});
}
}
}

在清理过程中,我关闭套接字并使用重用标志断开:

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: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond XX.XXX.XX.XX:80

Error Code: 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 中找到了以下注释:

If this socket has previously been disconnected, then BeginConnect must be called on a thread that will not exit until the operation is complete. This is a limitation of the underlying provider. Also the EndPoint that is used must be different.

我开始怀疑我的问题是否与此有关...我正在连接到不同的端点,但它们是什么意思,我们从中调用 BeginConnect 的线程在操作完成之前不得退出?

2.0 更新:
我问了一个related question我尝试使用“Async family”调用而不是“Begin family”调用,但我遇到了同样的问题!!!

最佳答案

我评论了这个问题:what is benefit from socket reuse in C# about socket reuse using Disconnect(true)/DisconnectEx() 这可能对你有帮助。

我个人认为这是对客户端代码的过度优化。

重新更新 1 到您的问题;不,如果是这种情况,你会得到一个 AbortedOperation 异常(见这里:VB.NET 3.5 SocketException on deployment but not on development machine),如果你在 Vista 或更高版本上运行,文档是错误的,因为它不强制执行“线程必须存在,直到重叠 I/O 完成”以前的操作系统执行的规则。

正如我在对相关问题的回复中所说的那样;使用此功能建立出站连接毫无意义。它很可能最初被添加到 Winsock API 以支持入站连接上 AcceptEx() 的套接字重用,其中,在使用 TransmitFile() 的非常繁忙的 Web 服务器上> 将文件发送给客户端(这是为重用断开连接似乎起源的地方)。文档指出它不能很好地与 TIME_WAIT 一起使用,因此将它用于您启动主动关闭的连接(从而将套接字置于 TIME_WAIT 中,请参阅 here )真的没有意义。

您能解释一下为什么您认为这种微优化在您的案例中实际上是必要的吗?

关于c# - 重用异步套接字 : subsequent connect attempts fail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5762276/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com