Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# (异步)正确地向多个客户端发送数据_C#_Asynchronous - Fatal编程技术网

C# (异步)正确地向多个客户端发送数据

C# (异步)正确地向多个客户端发送数据,c#,asynchronous,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(sendCal

如果我正确理解了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);
    }
}
/**
*我使用字典,因为我用登录密钥保存客户端
*/
私有void发送客户端(字典连接客户端、字符串数据)
{ 
foreach(connectedClients.Values中的客户端)
{
sendToClient(客户端、数据);
}
}
或者,我可以使用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.
            }
        }
    }
}
专用void发送客户端(字典连接客户端、字符串数据)
{
SocketAsyncEventArgs asyncEvent;
byte[]byteData=Encoding.UTF8.GetBytes(数据);//必须是UTF8
锁定(已连接客户端)
{
foreach(connectedClients.Values中的客户端)
{
尝试
{
asyncEvent=new SocketAsyncEventArgs();
asyncEvent.SetBuffer(byteData,0,byteData.Length);
client.Socket.SendAsync(asyncEvent);
}
捕获(例外情况除外)
{
//错误。
}
}
}
}
但这两种sendtoclient方法对我来说都很慢,而且/或者有时服务器无法将数据发送到任何客户端。包可能会丢失

示例:

客户端1收到103个数据包

客户端2收到107个数据包

客户端3收到102个数据包

Clientn收到106个数据包

但最后应该是111个数据包

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


提前感谢。

该代码看起来不错,但它取决于发起多个发送呼叫的呼叫代码。请注意,在前一个操作完成之前,您不能多次安全地调用
BeginSend
。请看这里: . 这可以解释您的非确定性数据包接收计数。因此,如果您想采用这种方法,您可能应该使用某种机制,在前面的调用完成之前防止多次调用
BeginSend

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


一旦有了任务对象,就可以使用“Task.ContinueWith”方法简单地安排下一次发送(而不与上一次发送重叠)。

您的意思是:Task.Factory.fromsync(stream.BeginSend、stream.EndSend、buffer、0、buffer.Length、client);我将bool设置为check,如果是,则为yes,否则为no。您的fromsync套接字调用看起来不错。但是不要使用单独的bool,任务具有IsCompleted属性。但实际上,您不应该再关心它是否已完成,因为您只需使用
ContinueWith
方法将新任务安排在完成后运行即可。底层任务将为您完成所有检查和计划。谢谢您,泰森,我现在正在测试它。