C#非阻塞Socket.Connect()

时间:2012-08-23 07:44:27

标签: c# sockets winsock nonblocking

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

需要注意的是:非阻塞!=异步:)

因此我通过关闭socket& amp;阻塞标志来实现以下方法: 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()?

吗?

4 个答案:

答案 0 :(得分:4)

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

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

  

Manual

     

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

     

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

     

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

但这正是你的代码所做的,所以这应该可行。

答案 1 :(得分:1)

您可以使用threadstasks启动Connect,而不会阻止主线程。

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

此外,您可以使用BackgroundWorker来避免此问题。

答案 2 :(得分:1)

实际上,您的代码正在我的系统上运行。但是,您当然需要一个接受TCP连接的服务器。如果你没有,那么你将永远等待。所以我猜你错过了一台服务器。

答案 3 :(得分:1)

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

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

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

if (hostname.Equals("localhost"))
{
    return IPAddress.Parse("127.0.0.1");
}
try
{
    return IPAddress.Parse(hostname);
}
catch (FormatException e)
{
    var ipHostInfo = Dns.GetHostEntry(hostname);
    return ipHostInfo.AddressList[0];
}

成功了(至少对我来说是这样!)