C#非阻塞Socket.Connect()

问题描述 投票:3回答:4

我选择不使用异步调用,因为它需要回调,我很好奇是否有办法通过使用与Unix类似的非阻塞套接字方法:Poll()来解决此问题,因为Asyn是专为Windows环境创建的。我正在研究是否可以在没有异步的情况下完成此操作。

要注意的是:NON-BLOCKING!= ASYNCHRONOUS:)]

因此,通过关闭socket和Poll()方法的阻塞标志,我有以下方法:

    try
    {
        IPEndPoint hostEp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
        Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        hostSock.Blocking = false;
        hostSock.Connect(hostEp);

    }
    catch (Win32Exception se)
    {
        if (ex.ErrorCode == 10035) // WSAEWOULDBLOCK is expected, means connect is in progress
        while (true)
        {
            Console.WriteLine("Connecting in progress");
            bool connected = hostSock.Poll(1000000, SelectMode.SelectWrite);
            if (connected)
            {
                Console.WriteLine("Connected");
                break;
            }

        }
    }

但是SelectMode.SelectWrite似乎并没有为我重新启动连接尝试。所以有什么问题?我该如何解决呢?我应该使用Select() instead of Poll()?

c# sockets winsock nonblocking
4个回答
3
投票

只需使用异步方法(ConnectAsync()),它们就是为此目的而设计的。不要将异常用于程序逻辑。

您可以同步ConnectAsync()一个TCP套接字而不会阻塞:

Connect()

Connect方法将阻塞,除非您在调用Connect之前专门将Blocking属性设置为false。如果您使用的是像TCP这样的面向连接的协议,并且您确实禁用了阻止,则Connect将抛出SocketException,因为它需要时间来建立连接。

您可以使用SocketException.ErrorCode来获取特定的错误代码。获取此代码后,请参阅MSDN库中的Windows套接字版本2 API错误代码文档,以获取有关该错误的详细说明。

如果错误返回WSAEWOULDBLOCK,则远程主机连接已由面向连接的Socket启动,但尚未成功完成。使用轮询方法确定套接字何时完成连接。

但是这正是您的代码所要做的,因此应该可以正常工作。


1
投票

您可以使用Manualthreads来启动Connect而不会阻塞主线程。

由于跨线程保护,如果需要与UI(WinForms / WPF)进行交互,将会增加复杂性。

此外,您也可以使用tasks避免出现此问题。


1
投票

实际上,您的代码正在我的系统上运行。但是,您当然需要一台接受TCP连接的服务器。如果没有,那您​​将永远等待。因此,我想您缺少服务器。


1
投票

我有确切的问题,但是对我来说答案很愚蠢:我的代码中有用于从字符串中获取IpAddress的股票代码(来自BackgroundWorker:]]

microsoft

这很好,但是我的测试是针对“ 127.0.0.1:9000”进行的,由于某种原因,该网关控制了我实际的以太网连接的IP地址。将解析机制更改为:

 var ipHostInfo = Dns.GetHostEntry(hostname);
 return ipHostInfo.AddressList[0];

没有花招(至少对我来说!)

© www.soinside.com 2019 - 2024. All rights reserved.