首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“广播”到TCP客户端列表的最快方法

“广播”到TCP客户端列表的最快方法
EN

Stack Overflow用户
提问于 2012-07-22 06:17:03
回答 1查看 3.1K关注 0票数 3

我目前正在用C#编写一个自下而上的聊天服务器。

它就像一个单独的大房间,里面有所有的客户,然后你也可以发起私人聊天。我还列出了将来集成多个房间的代码(但现在不是必需的)。

写这篇文章主要是为了好玩,但也是因为我要为像我这样的年轻人创建一个新的聊天网站,因为丹麦已经没有人了。

我刚刚用170个客户端测试了它(用Javascript编写,带有JQuery和一个连接到socket的闪存桥)。在本地网络上,从发送到它的消息传递的响应时间不到1秒。但现在我在考虑我能从中挤出什么样的性能。

我可以看到,如果我连接两个客户端,然后连接168个其他客户端,并在客户端2上写入并查看客户端1,它会立即出现在客户端1上。CPU使用率和RAM使用率完全没有显示出服务器压力的迹象。它处理得很好,我认为它至少可以扩展到1000 - 1500,没有任何问题。

然而,我注意到了一些事情,那就是如果我再次打开170个客户端,在客户端1上发送一条消息,并在客户端170上观看,会有一个大约750毫秒的日志。我知道问题所在,那就是,当服务器收到聊天消息时,它会将其广播给服务器上的每个客户端。然而,它确实需要枚举所有这些客户端,这需要时间。现在的延迟对于聊天来说是可以接受的,但我担心客户端1发送到客户端750 (还没有测试)可能需要2-3秒。当我开始每秒可能收到2-3条消息时,我也很担心。

因此,总而言之,我想加快服务器广播过程。我已经在使用一个并行的foreach循环了,我还在使用异步套接字。

以下是广播代码:

代码语言:javascript
复制
  lock (_clientLock)
        {
            Parallel.ForEach(_clients, c =>
            {
                c.Value.Send(message);
            });
        }

下面是在每个客户端上调用的send函数:

代码语言:javascript
复制
try {
        byte[] bytesOut = System.Text.Encoding.UTF8.GetBytes(message + "\0");
        _socket.BeginSend(bytesOut, 0, bytesOut.Length, SocketFlags.None, new AsyncCallback(OnSocketSent), null);
        }
        catch (Exception ex) { Drop(); }

我想知道有没有什么方法可以加速这个过程?我曾考虑过编写某种帮助器类,接受que中的消息,然后使用大约20个线程来拆分广播列表。

但是我想知道你对这个话题的看法,我是一个学生,我想学习!

顺便说一句。我喜欢你在发布到堆栈溢出时发现代码中的问题的方式。我现在已经创建了一个重载函数,在使用广播时接受来自服务器类的字节数组,因此UTF-8转换只需要发生一次。另外,为了安全起见,字节数组长度的计算现在只进行一次。请参阅下面的更新版本。但我仍然对改进这一点的方法感兴趣!

更新的广播功能:

代码语言:javascript
复制
 lock (_clientLock)
        {
            byte[] bytesOut = System.Text.Encoding.UTF8.GetBytes(message + "\0");
            int bytesOutLength = bytesOut.Length;
            Parallel.ForEach(_clients, c =>
            {
                c.Value.Send(bytesOut, bytesOutLength);
            });
        }

已更新客户端对象上的发送函数:

代码语言:javascript
复制
 public void Send(byte[] message, int length)
    {
        try
        {
            _socket.BeginSend(message, 0, length, SocketFlags.None, new AsyncCallback(OnSocketSent), null);
        }
        catch (Exception ex) { Drop(); }
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-22 06:27:51

~1s sounds really slow for a local network (本地网络的~1s声音非常慢。平均LAN延迟为0.3ms。Nagle是启用还是禁用?我猜它已经启用了..。所以:更改它(Socket.NoDelay)。当然,这意味着您必须为不以过于零碎的方式写入套接字而负责-所以不要逐个字符地传递消息。在内存中组装要发送的消息(或者更好:多个未完成的消息),并将其作为一个单元发送。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11596263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档