(异步)正确地将数据发送到多个客户端

时间:2012-02-27 00:28:33

标签: c# asynchronous

如果我理解了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);
    }
}

或者在另一方面,我可以使用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 方法对我来说都很慢和/或有时服务器无法将数据发送到任何客户端。数据包可能会丢失。

示例:

Client1收到103个数据包

Client2收到107个数据包

Client3收到了102个数据包

Clientn收到了106个数据包

但最后应该是111个数据包。

是否有其他方法/逻辑/技术将一个数据发送给多个客户端,或者我的示例中是否存在使用错误的内容?

提前致谢。

1 个答案:

答案 0 :(得分:1)

该代码看起来不错,但它取决于启动多个发送调用的调用代码。请注意,在每个上一个操作完成之前,您无法安全地多次调用BeginSend。看这里: Async Socket Writes - Potential for send operations to get mixed up? (.NET Sockets)。这可以解释您的非确定性数据包接收计数。因此,如果你想采用这种方法,你应该使用一些机制来阻止多个BeginSend调用,直到之前的调用完成。

但我最近一直在做的是使用新的TPL及其Task.Factory.FromAsync方法将旧的APM样式Begin / End X转换为Task<T>

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

一旦有了Task对象,就可以使用`Task.ContinueWith'方法安排下一次发送(不重叠前一次)。

相关问题