2012-08-23 391 views
2

我選擇不使用異步調用,因爲它需要回調,我只是好奇,是否有辦法通過利用解決這個類似於Unix的非阻塞套接字方法:Poll(),Asyn是專門爲Windows環境創建的。我正在研究這是否可以在沒有異步的情況下完成。C#非阻塞Socket.Connect()

需要說明的是:無阻塞=異步 :)

因此,我已通過關閉插座的阻斷標誌& 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()?

+1

僅限使用選擇是否在同一時間在多個套接字上接收。 – Slugart

回答

4

只需使用異步方法(ConnectAsync()),它們就是爲了這個。不要爲程序邏輯使用異常。

您可以同步Connect()無阻塞TCP套接字:

Manual

Connect方法將阻止,除非您特別的粘連性假前設置爲呼叫連接。如果您正在使用面向連接的協議(如TCP),並且您禁用了阻止,則Connect將拋出SocketException,因爲它需要時間來建立連接。

您可以使用SocketException.ErrorCode獲取特定的錯誤代碼。獲得此代碼後,請參閱MSDN庫中的Windows套接字版本2 API錯誤代碼文檔以獲取錯誤的詳細說明。

如果錯誤返回WSAEWOULDBLOCK,則遠程主機連接已由面向連接的Socket啓動,但尚未成功完成。使用輪詢方法來確定Socket何時完成連接。

但是,這正是你的代碼所做的,所以這應該工作。

+0

是的,我的確瞭解禁用阻塞的後果,這就是爲什麼我有一個重試連接的漁獲。如前所述,我選擇不使用asych方法,您是否有針對此問題的解決方案? :) – Roylee

+0

+1 CodeCaster。 爲什麼你不想使用異步方法?我不知道是否存在其他方法,異步方法存在的:-),如果你不使用異步方法,你的代碼在哪裏強制插座連接時間... –

+0

不,我只是好奇如果有辦法通過使用類似Unix的非阻塞套接字方法來解決這個問題:Poll(),Asyn僅適用於窗口環境。我正在研究,如果這可以完成沒有Asyn只。 :) – Roylee

1

您可以使用threadstasks以啓動Connect而不阻塞主線程。

這會增加複雜性,如果需要與UI(WinForms/WPF)交互,由於跨線程保護。您可以使用BackgroundWorker來避免此問題。

+1

在作者的問題:「沒有異步完成」 –

+1

不,他說沒有異步方法,由於回調和增加了BeginConnect()和EndConnect()的補充。或者,至少,這是我所理解的。 – JoanComasFdz

1

其實,你的代碼在我的系統上工作。但是,您當然需要一個接受TCP連接的服務器。如果你沒有這個,那麼你將永遠等待。所以我猜你錯過了一臺服務器。