2012-02-27 60 views
1

將數據發送到多個客戶端如果我正確理解BeginSend的邏輯:(異步)正確地

private void sendToClient(Client client, String data) 
{ 
    byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8 

    client.BeginSend(byteData, 0, byteData.Length, 0, 
        new AsyncCallback(sendCallback), client); 
} 
private void sendCallback(IAsyncResult iar) 
{ 
    Socket client = (Socket)iar.AsyncState; 
    int bytesSent = client.EndSend(iar); 
} 

我已經正確數據發送到一個客戶端。

但是,如果我要發送的數據,更多的客戶:

/** 
* I am using dictionary, because I hold the clients with login-key 
*/ 
private void SendToClients(Dictionary<string, Client> connectedClients, String data) 
{ 
    foreach(Client client in connectedClients.Values) 
    { 
     sendToClient(client, data); 
    } 
} 

或者在anotherway,我可以使用的SocketAsyncEventArgs發送所有客戶:

private void sendToClients(Dictionary<string, Client> connectedClients, String data) 
{ 
    SocketAsyncEventArgs asyncEvent; 
    byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8 

    lock (connectedClients) 
    { 
     foreach (Client client in connectedClients.Values) 
     { 
      try 
      { 
       asyncEvent = new SocketAsyncEventArgs(); 
       asyncEvent.SetBuffer(byteData, 0, byteData.Length); 
       client.Socket.SendAsync(asyncEvent); 
      } 
      catch (Exception ex) 
      { 
       //ERROR. 
      } 
     } 
    } 
} 

但兩者sendToClients方法的工作對我來說很慢和/或有時服務器無法將數據發送到任何客戶端。數據包可能會丟失。

實施例:

客戶端1接收的103包

客戶機2收到的107包

Client3 102級接收的數據包

Clientn 106級接收的數據包

但應111包最後。

是否有另一種方法/邏輯/技術發送一個數據給多個客戶端,或者在我的例子中是否有錯誤?

在此先感謝。

回答

1

該代碼看起來不錯,但它取決於啓動多個發送調用的調用代碼。請注意,在每個先前操作完成之前,您無法安全地撥打BeginSend。見這裏: Async Socket Writes - Potential for send operations to get mixed up? (.NET Sockets)。這可能會解釋您的非確定性數據包接收計數。因此,如果你想採用這種方法,你應該使用一些機制,在先前的呼叫完成之前阻止多個呼叫BeginSend

但我一直在做最近使用新的TPL及其Task.Factory.FromAsync方法來轉換舊的APM風格的開始/結束X爲Task<T>

http://blogs.msdn.com/b/pfxteam/archive/2009/06/09/9716439.aspx

一旦你的任務目標是使用'Task.ContinueWith'方法可以很方便地安排下一次發送(不重疊前一個)。

+0

你的意思是類似於:任務 .Factory.FromAsync( stream.BeginSend,stream.EndSend,buffer,0,buffer.Length,client);我設置布爾檢查,如果其相符 – Racooon 2012-02-27 01:06:51

+0

是的,沒有。您的FromAsync套接字調用看起來不錯。但不要使用單獨的布爾,該任務有一個IsCompleted屬性。但是,實際上,如果它已完成或不完成,您就不應該在意,因爲您只需使用「ContinueWith」方法完成新任務的運行即可。基本任務將爲您執行所有檢查和計劃。 – Tyson 2012-02-27 01:13:58

+0

謝謝泰森,我現在正在測試它。 – Racooon 2012-02-27 01:39:11