再利用异步套接字:随后的连接尝试失败 [英] Reuse asynchronous socket: subsequent connect attempts fail

查看:619
本文介绍了再利用异步套接字:随后的连接尝试失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想重复使用异步HTTP客户端的插座,但我不能够围绕连接到主机的第二次。我基本上把我的异步HTTP客户端作为一个状态机具有以下状态:

I'm trying to reuse a socket in an asynchronous HTTP client, but I'm not able to connect to the host the second time around. I basically treat my asynchronous HTTP client as a state machine with the following states:


  • 可用:插槽可供使用

  • 连接:套接字连接到终点

  • 发送:套接字发送数据到端点

  • 接收:套接字从端点接收数据

  • 失败:有一个插座故障

  • 清理:清理套接字状态

在我所说的连接状态 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);
            });
        }
    }
}

在清理我关闭插座和断开连接与再利用标志:

In the cleanup I Shutdown the socket and Disconnect with a reuse flag:

private void CleanUp()
{
    lock (_sync) // re-entrant lock
    {
        // Perform cleanup 
        if (_reusableSocket.Connected)
        {
            _reusableSocket.Shutdown(SocketShutdown.Both);
            _reusableSocket.Disconnect(true);
        }
        ChangeState(EClientState.Available);
    }
}

BeginConnect 导致超时和异常后续调用:

Subsequent calls to BeginConnect result in a timeout and an exception:

SocketException:连接尝试
  失败,因为连接的方没有
  一段时间后没有正确响应
  时间或建立的连接失败
  因为连接主机未能
  回应XX.XXX.XX.XX:80

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

错误code:10060

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

什么我需要做的是能够重复使用的插座连接到不同的主机?

What do I have to do to be able to reuse the socket to connect to a different host?

请注意:我有<击>不是尝试重新连接到同一个主机,但<击>我假设同样的事情发生(即无法连接)

Note: I have not tried to re-connect to the same host, but I assume the same thing happens (i.e. fails to connect).

更新结果
我发现BeginConnect 的文档中的以下注意事项:

Update
I found the following note in the documentation of BeginConnect:

如果此套接字具有previously被断开,则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线程必须不会退出,直到操作完成?

I'm starting to wonder if my issue has something to do with that... I am connecting to a different EndPoint, but what do they mean that the thread from which we call BeginConnect must not exit until the operation is complete?

更新2.0:结果
我问了一个<一个href=\"http://stackoverflow.com/questions/5764921/whats-the-difference-between-beginconnect-and-connectasync\">related问题
我使用异步家庭调用,而不是开始家庭的呼叫尝试,但我得到了同样的问题!

Update 2.0:
I asked a related question and I tried using the "Async family" calls instead of the "Begin family" calls, but I get the same problem!!!

推荐答案

我谈到了这个问题:<一href=\"http://stackoverflow.com/questions/4133150/what-is-benefit-from-socket-reuse-in-c/4137697#4137697\">what是使用断开连接(真)/ DisconnectEx(),这可能会帮助你。

I commented on this question: what is benefit from socket reuse in C# about socket reuse using Disconnect(true)/DisconnectEx() and this may help you.

我个人认为这是一个优化太远客户端code。

Personally I think it's an optimisation too far in client code.

重新更新1到你的问题;不,你会得到一个AbortedOperation异常,如果是这样的话(在这里看到:<一href=\"http://stackoverflow.com/questions/1609706/vb-net-3-5-socketexception-on-deployment-but-not-on-development-machine/1609915#1609915\">VB.NET 3.5 SocketException有关部署而不是开发机器)和文档上是错误的,如果你在Vista上运行或更高版本,因为它不执行必须存在线程,直到后重叠I / O完成裁定previous操作系统执行。

Re update 1 to your question; no, you'd get an AbortedOperation exception if that were the case (see here: VB.NET 3.5 SocketException on deployment but not on development machine) and the docs are wrong if you're running on Vista or later as it doesn't enforce the "thread must exist until after overlapped I/O completes" rule that previous operating systems enforce.

正如我已经在答复中链接的问题说,有一个在使用此功能,出站连接建立的非常小的点。这可能是因为它最初被添加到的Winsock API来支持的AcceptEx插座重用()对入站连接,在那里,一个非常繁忙的Web服务器上使用的TransmitFile()将文件发送给客户(这是为断开重用似乎起源)。该文档的状态,它不使用它,你开始主动关闭(从而把插座插入连接与 TIME_WAIT 等发挥出色TIME_WAIT ,见<一href=\"http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html\"相对=nofollow>这里)并没有真正意义。

As I've already said in the reply to the linked question; there's very little point in using this functionality for outbound connection establishment. It's likely that it was originally added to the Winsock API to support socket reuse for AcceptEx() on inbound connections, where, on a very busy web server that was using TransmitFile() to send files to clients (which is where disconnect for reused seems to have originated). The docs state that it doesn't play well with TIME_WAIT and so using it for connections where you initiate the active close (and thus put the socket into TIME_WAIT, see here) doesn't really make sense.

你能解释一下为什么你认为这条微优化实际上是必要的,你的情况?

Can you explain why you think this micro optimisation is actually necessary in your case?

这篇关于再利用异步套接字:随后的连接尝试失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆