异步发送到多个客户端和FromAsync的正确使用? [英] Async Send to multiple clients and correct usage of FromAsync?

查看:185
本文介绍了异步发送到多个客户端和FromAsync的正确使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在服务器上500连接的客户端。服务器中的每N秒将数据发送到所有客户端。

I have 500 connected clients on the server. Server sends data to all clients in every N sec.

当服务器将数据发送到客户端的结果是:

When the server sends data to clients the result is:

-----------Result-----------
Client1 received : 102 datas
Client2 received : 109 datas
Client3 received : 105 datas
Client4 received : 108 datas
Client5 received : 108 datas
ClientN received : 107 datas

但应110 DATAS在端

But it should be 110 datas at the end.

我用下面的code发送数据给客户

I am using the following code to send data to clients

public static class AsyncSend
{
    public static Task<int> SendAsync(this Socket socket, byte[] buffer, int offset, int count)
    {
        return new Task<int>(() =>
        {
            return Task.Factory.FromAsync<int>(
                           socket.BeginSend(buffer, offset, count, SocketFlags.None, null, socket),
                     socket.EndSend).Result;
        });
    }
}

class ServerTest
{
  private Thread sendThread;
  private Dictionary<String, Client> connectedClients;

  public ServerTest()
  {
    connectedClients = new Dictionary<String, Client>();
  }

  public void receive()
  {
    //here server receives data from another server
    //When server receives new data then fires the newDataReceived(String data) method.

    newDataReceived(data);
  }

  public void newDataReceived(String data)
  {
    sendThread = new Thread(new ParameterizedThreadStart(sendToClients));
    sendThread.Start(data);
  }

  private void sendToClients(object dataObj)
  {
    try
    {
      int totalConnectedClients = connectedClients.Count;

      if (totalConnectedClients > 0)
      {
        lock (connectedClients)
        {
          byte[] buffer = Encoding.UTF8.GetBytes((string)dataObj);
          byte[] cBuffer = new SCompressor().Compress(buffer);

          foreach (Client client in connectedClients.Values)
          {
            Task<int> task = AsyncSend.SendAsync(client.Socket, cBuffer, 0, cBuffer.Length);
            task.Start();
          }
        }
      }
    }
    catch (Exception ex)
    {
      //ERROR.
    }
  }

有另一种方式,或如何正确而有效地将数据发送到多个客户端?

Is there another way or how to send data to multiple clients correctly and efficiently?

如果你能请给我的例子。

Please show me examples if you can.

谢谢意见。

推荐答案

我有一些点你:

您可以通过发送每一个劲多余的任务提高效率:

You can improve efficiency by getting rid of one superfluous task per send:

public static Task<int> SendAsync(this Socket socket, byte[] buffer, int offset, int count)
{
        return Task.Factory.FromAsync<int>(
                       socket.BeginSend(buffer, offset, count, SocketFlags.None, null, socket),
                 socket.EndSend);
//Don't explicitly start the return value of this method. The task will already be started.
}

您发送异步的使用是正确的,据我可以告诉(除不需要的任务)。

You usage of asynchronous sending is correct as far as I can tell (except for the unneeded task).

您使用UDP?如果是的话,这可以解释为什么一些数据丢失。

Are you using UDP? If yes, that would explain why some data is missing.

有没有被捕捞的错误?如果是的话,循环将中止,而不是所有的客户端会得到他们的数据。

Is there an error that is being caught? If yes, the loop will abort and not all clients will get their data.

您有一个竞争条件:

int totalConnectedClients = connectedClients.Count;

这应该在锁内发生。你不能安全地读取计数,而其他线程可能更新该字典。

This should happen inside the lock. You cannot safely read Count while other threads might update this dictionary.

你是如何获得这些数据?也许bug是在接收端。请张贴一些code。

How are you receiving the data? Maybe the bug is on the receive-side. Please post some code.

编辑:

如果两个并发接收到正在运行什么?这将导致一个错误:客户可以先接受最新的数据,那么第二个较旧的数据。我建议你​​不要启动新线程每次接收数据的时间。相反,有永久运行的线程是从BlockingCollection使用GetConsumerEnumerable方法获取新的数据。您newDataReceived方法只会排队进入这个BlockingCollection。你可以在这里找到一个很好的介绍:<一href=\"http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx\" rel=\"nofollow\">http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx

What if two concurrent receives are running? This would cause a bug: Clients could receive the newest data first, then the older data second. I recommend that you do not start a new thread every time you receive data. Instead, have a thread running permanently which is pulling new data from a BlockingCollection using the GetConsumerEnumerable method. Your newDataReceived method would just enqueue into this BlockingCollection. You can find an excellent introduction here: http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx

这篇关于异步发送到多个客户端和FromAsync的正确使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆