2012-02-27 82 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