2012-02-27 1 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); 
} 

を私が正しく1つのクライアントにデータを送ってきました。

しかし、私はより多くのクライアントのためにデータを送信する場合:

/** 
* 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が受信クライアント3はClientn 106のパケットに

を受けたが、それは111のパケットであるべきである102のパケット

を受信

107のパケット

を受信最後に。

複数のクライアントに1つのデータを送信するための方法やロジックや技術がありますか、私の例で間違って使われていますか?

ありがとうございます。

答えて

1

このコードは大丈夫ですが、複数の送信呼び出しを開始する呼び出しコードによって異なります。以前の操作がすべて終了する前に、安全にBeginSendに何度も呼び出すことはできません。ここをクリックしてください: Async Socket Writes - Potential for send operations to get mixed up? (.NET Sockets)これは、あなたの非決定的なパケット受信カウントを説明するかもしれません。だから、もしあなたがこのアプローチをしたいのであれば、前の呼び出しが完了する前に複数のBeginSend呼び出しを防ぐいくつかの仕組みを使うべきでしょう。

しかし、私はTask<T>に古いAPMスタイル開始/終了Xを変換するために、新しいTPLとそのTask.Factory.FromAsyncメソッドを使用している最近やっている:

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

+0

はい、いいえ。あなたのFromAsyncソケット呼び出しがうまくいくように見えます。しかし、別のブールを使用しないでください。タスクにはIsCompletedプロパティがあります。しかし、実際には、完了したかどうかを気にする必要はありません。新しいタスクの実行が完了すると、 'ContinueWith'メソッドを使用して終了します。基礎となるタスクは、すべてのチェックとスケジューリングを行います。 – Tyson

+0

タイソンありがとう、私は今それをテストしています。 – Racooon

関連する問題