2

我选择不使用异步调用,因为它需要回调,我只是好奇是否有办法通过使用类似 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() 吗?

4

4 回答 4

3

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

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

手册

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

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

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

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

于 2012-08-23T07:46:44.963 回答
1

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

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

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

于 2012-08-23T08:04:46.927 回答
1

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

于 2016-01-31T22:12:57.937 回答
1

我有确切的问题,但对我来说答案相当愚蠢:我的代码有用于从字符串中获取 IpAddress 的库存代码(来自microsoft):

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

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

于 2020-04-16T17:51:19.937 回答