zoukankan      html  css  js  c++  java
  • 延时拼包机制让c# socket实现海量数据包广播吞吐

        之前已经简单的测试了c# socket的数据吞吐处理能力,结果虽然比较理想;但以这样的数据包处理量在某些场景下是远远不够用的,在某些应用场景中每秒要处理的数据包不是1,2W个可能几W,上10W或更多的数据包吞吐。在一个游戏场景中同场景存在100用户,每个用户的变更都会通知其他199的用户,如果每个用户平均每秒变更3次,那服务端每秒接收转发的数据包就是100x100x3=3w个。如果是200个用户同场景,那所每秒所面对的处理包会是200x200x3=12W个,想c# socket提供这么密集的IO处理是不太可能的事情,即使是可以那也要很不错的硬件支撑。

        从软件上去解决这问题那只能选择减少IO操作,之前的测试表明SendAsync这相的IO操作是非常损耗资源。既然问题已经知道发生在什么地方,我们可以采用减少SendAsync又不影响交互性来达到这一点。大家知道网络访问存在一个延时的系数,通过在可接受的延时区间可以把发送的A的N个数据包打包到一个buffer里,然后进行一次SendAsync操作,原本在这一时间段时有100个消息包发给A,那可以打包成一个这样SendAsync的操作就可以从原来的100次变成一次;那些这节省是相当可观的,当然这个设计尽可能根据当前调度情况来确定,调度空闲的情况下不合拼,调度存在压力的时候进行一个合拼处理。

       以下是针对这个设计的测试结果:

    测试硬件:

    server:Core2 4300 1.8G 2G win2003

    client1:Core i7 Q740 1.7G 4G win764

    client2:P4 2.4G 1G WIN2003

    测试逻辑:

    每个client程序开启50个连接,每个连接秒产生3次座标变化告诉服务端,由服务端专发给其他client.

    定期为每个client发送ping包,检测服务器处理和回发的延时时间。

    数据结构:

    public class ChangePostion:IMessage
        {
            public int X
            {
                get;
                set;
            }
            public int Y
            {
                get;
                set;
            }
            public string ID
            {
                get;
                set;
            }
    
            public void Save(BufferWriter writer)
            {
                writer.Write(X);
                writer.Write(Y);
                writer.WriteBlock(ID);
            }
    
            public void Load(BufferReader reader)
            {
                X = reader.ReadInt32();
                Y = reader.ReadInt32();
                ID = reader.ReadBlock();
            }
            private static Random ran = new Random();
            public static ChangePostion GetPoint()
            {
                ChangePostion cp = new ChangePostion();
                cp.X = ran.Next(1, 399);
                cp.Y = ran.Next(1, 399);
                return cp;
            }
        }
        public class Ping : IMessage
        {
            public string ID
            {
                get;
                set;
            }
            public DateTime Ticks
            {
                get;
                set;
            }
    
            public void Save(BufferWriter writer)
            {
                writer.WriteBlock(ID);
                
            }
    
            public void Load(BufferReader reader)
            {
                ID = reader.ReadBlock();
            }
        }

    100人同场景测试

     服务端程序情况:

     client情况

    测试情况来看每个client每秒接收1.6w个数据包,两个client接收大概3.2W个数据包,服务端的下行带宽是2MB/秒,每秒处理3.2W对象写入缓冲发送。

    200人同场景测试

     服务器端情况

    客户端情况

    测试情况来看每个client每秒接收3.2w个数据包,4个client接收大概13W个数据包,服务端的下行带宽是8MB/秒,每秒处理13W对象写入缓冲发送

    注意

    当使用了拼包的时候就要考虑一下Socket.NoDelay是否需要开启,还有client的ReceiveBufferSize是否需要加大,在测试过程中当存在大量数据包接收的时候有个别client连接接收到的数据不正常,之于这个问题是.net的内置缓冲问题还是程序设计上的缺陷还在追查中(查明原因后会编写文章讲述问题情况)。

    下载测试程序

    BeetleTest20111127.rar (935.91 kb)

    跑测试程序最好把client分布在不同机器上

     通过上面的测试可以让想用C# Socket做应用的朋友更进一步了解它的处理能力到底怎样。对于想要源码的朋友就不需要问了,对于些问题的分析可以访问:www.henryfan.net

    访问Beetlex的Github
  • 相关阅读:
    BDB c++例子,从源码编译到运行
    Linux的nm查看动态和静态库中的符号
    转:js包装DOM对象
    svn笔记4属性Properties
    c++ 友元函数
    转:js包装DOM对象
    整除规则(原理,性质)
    回溯法求幂集
    转:Javascript继承机制的设计思想
    javascript prototype __proto__区别
  • 原文地址:https://www.cnblogs.com/smark/p/2265836.html
Copyright © 2011-2022 走看看