繁体   English   中英

C# 非阻塞 Socket.Connect()

[英]C# Non-blocking Socket.Connect()

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

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

因此,我通过关闭 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() 而不是 Poll() 吗?

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

您可以在不阻塞的情况下同步Connect()一个 TCP 套接字:

手册:

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

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

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

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

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

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

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

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

我有确切的问题,但对我来说答案很愚蠢:我的代码具有用于从字符串(来自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];
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM