2012-11-08 146 views
2

我對Async方法實現的功能有點困惑。在查找如何讓服務器接受多個連接時,我遇到了它。在查找Aync在C#中完全實現的功能時,會發生什麼讓我困惑的是,從我可以告訴它的不是它自己的線程。但是,它也可以讓你避免鎖定和拖延。舉例來說,如果我有以下幾點:瞭解C#中的異步(套接字)

ConnectionManager() 
    { 
     listener = new TcpListener(port); 
     listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener); 
    } 

    public void acceptConnection(IAsyncResult ar) 
    { 
     //Do stuff 
    } 

這是否意味着,一旦它找到一個連接,它執行「acceptConnection」的功能,但隨後繼續通過調用函數來執行? (在這種情況下超出範圍)。這如何讓我創建一個服務器應用程序,可以接受多個客戶端?即使我之前使用線程來管理服務器/客戶端交互,我對這個概念還是比較陌生的。如果我有點模糊,請告訴我。我在MSDN上查找了多個示例,但仍然有點困惑。提前謝謝!

回答

3

儘快找到一個連接,它執行 「acceptConnection」 功能

然後繼續通過調用函數來執行?

什麼是異步方式實現

如果使用得當,它可以處理/高得多的請求數量第二用更少的資源。

想象一下,您正在創建一個服務器,該服務器應該接受10個TCP端口上的連接。

與封閉API,你必須創建10個線程剛剛接受插座。線程是昂貴的系統資源,例如每個線程都有自己的堆棧,並且線程之間的切換需要相當長的時間。如果客戶端連接到某個套接字,則操作系統將不得不喚醒相應的線程。

使用異步API,您發佈了10個異步請求。當客戶端連接時,您的acceptConnection方法將由CLR線程池中的線程調用。

還有一件事。

如果要在等待異步I/O操作完成後繼續執行調用者函數,則應考慮新的C#的async/await語法,它允許您這樣做。該功能可用作Visual Studio 2010的獨立庫「Async CTP」,幷包含在Visual Studio 2012中。

+0

我不認爲推薦Async CTP是一個好主意,那只是預覽代碼。 – svick

+0

@svick,它工作的很好,而且自SP1刷新以來,它有一個上線許可證,所以它不是「只是預覽代碼」。 – Soonts

+0

我在Windows 8應用程序中實現HTTP客戶端的東西時看到過這段代碼。然而,這些調用的大多數示例代碼都等待着哪些強制您等待該函數超出範圍或返回某些內容,然後再繼續。 –

2

我不自稱是一個C#或插座大師,但是從我瞭解你上面已經有了將接受第一個連接,然後沒有更多的代碼。您需要建立另一個BeginAccept。

喜歡的東西:除了異步連接

因此,通過使用異步
TcpListener listener = null; 

ConnectionManager() 
{ 
    listener = new TcpListener(port); 
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener); 
} 

public void acceptConnection(IAsyncResult ar) 
{ 
    // Create async receive data code.. 

    // Get ready for a new connection 
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener); 

} 

接收數據時,接受連接很快完成,並建立偵聽新的連接。我想你也可以重新排序。

對於直插座連接(不的TcpListener),這是我用什麼:

(connectedClient是我自己的類,它處理接收&發射功能,包含有關連接的其他信息)。

int Port = 7777; // or whatever port you want to listen on 
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port); 
listenSocket = new Socket(AddressFamily.InterNetwork, 
      SocketType.Stream, ProtocolType.Tcp); 

listenSocket.Bind(ipLocal); 

// create the call back for any client connections... 
     listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null); 

private void OnClientConnection(IAsyncResult asyn) 
    { 
     if (socketClosed) 
     { 
      return; 
     } 

     try 
     { 
      Socket clientSocket = listenSocket.EndAccept(asyn); 

      ConnectedClient connectedClient = new ConnectedClient(clientSocket, this); 

      connectedClient.MessageReceived += OnMessageReceived; 
      connectedClient.Disconnected += OnDisconnection; 
      connectedClient.MessageSent += OnMessageSent; 

      connectedClient.StartListening(); 

      // create the call back for any client connections... 
      listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null); 

     } 
     catch (ObjectDisposedException excpt) 
     { 
      // Deal with this, your code goes here 

     } 
     catch (Exception excpt) 
     { 
      // Deal with this, your code goes here 
     } 

    } 

我希望這回答了您要找的內容?

+0

我喜歡你如何爲連接使用事件處理。我可能會遵循這種模式:)。這非常有幫助,謝謝! –