3

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

就像一个单独的大房间,所有客户都在里面,然后你也可以发起私人聊天。我还为将来集成多个房间(但现在没有必要)制定了代码。

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

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

我可以看到我是否连接了两个客户端,然后连接了 168 个其他客户端,并在客户端 2 上写入并观察客户端 1,它立即出现在客户端 1 上。CPU 使用率和 RAM 使用率根本没有显示服务器压力的迹象。它处理得很好,我认为它可以扩展到至少 1000 - 1500 没有丝毫问题。

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

所以总结一下,我想加快服务器广播过程。我已经在使用并行 foreach 循环,并且还在使用异步套接字。

这是广播代码:

  lock (_clientLock)
        {
            Parallel.ForEach(_clients, c =>
            {
                c.Value.Send(message);
            });
        }

这是在每个客户端上调用的发送函数:

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(); }

我想知道是否有任何方法可以加快速度?我考虑过编写某种辅助类来接受队列中的消息,然后使用大约 20 个线程来拆分广播列表。

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

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

更新广播功能:

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

更新了客户端对象的发送功能:

 public void Send(byte[] message, int length)
    {
        try
        {
            _socket.BeginSend(message, 0, length, SocketFlags.None, new AsyncCallback(OnSocketSent), null);
        }
        catch (Exception ex) { Drop(); }
    }
4

1 回答 1

3

~1s对于本地网络来说听起来真的很慢。平均 LAN 延迟为 0.3 毫秒。Nagle 是启用还是禁用?我猜它已启用......所以:改变那个(Socket.NoDelay)。当然,这确实意味着您必须负责不以过于分散的方式写入套接字 - 所以不要逐个字符地滴下消息。在内存中组装要发送的消息(或者更好的是:多个未完成的消息),并将其作为一个单元发送。

于 2012-07-21T22:27:50.797 回答