簡體   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