代码之家  ›  专栏  ›  技术社区  ›  srain

如何通过套接字利用100%的网络带宽?

  •  2
  • srain  · 技术社区  · 11 年前

    我有一个服务器和一个客户端。正在不同的服务器上工作。这两个服务器都有 两个1000M网络适配器 .

    我正在使用 tcp阻塞套接字 在服务器和客户端中。

    服务器

    一旦套接字被接受,将启动一个新线程来处理请求。它的工作原理如下:

    while(1) {
        recv();  /* receive a char */
        send();  /* send a line */
    }
    

    客户端只需向服务器发送一个字符,服务器就会向客户端发送一行文本。正文的长度约为200。

    该行已预先加载到内存中。

    客户

    客户端使用不同的线程连接到服务器。连接后,其工作方式如下:

    while(1) {
        send();  /* send a char */
        recv();  /* receive a line and  */
    }
    

    带宽使用情况

    当我在客户端使用100个线程时(结果几乎相同),我在服务器中获得了以下网络流量:

    tsar -l -i 1 --traffic
    

    结果:

    Time              -------------traffic------------
    Time               bytin  bytout   pktin  pktout
    06/09/14-23:12:56   0.00    0.00    0.00    0.00
    06/09/14-23:12:57  63.4M  155.3M  954.6K  954.6K
    06/09/14-23:12:58   0.00    0.00    0.00    0.00
    06/09/14-23:12:59  60.1M  147.3M  905.4K  905.4K
    06/09/14-23:13:00   0.00    0.00    0.00    0.00
    06/09/14-23:13:01  57.5M  140.8M  866.5K  866.4K
    

    sar -n DEV 1 :

    11:20:46 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
    11:20:47 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    11:20:47 PM      eth0 478215.05 478217.20  31756.46  77744.95      0.00      0.00      0.00
    11:20:47 PM      eth1 484318.28 484318.28  32162.05  78724.16      0.00      0.00      1.08
    11:20:47 PM     bond0 962533.33 962535.48  63918.51 156469.11      0.00      0.00      1.08
    

    问题:

    理论上 (bytin + bytout) 可以是 256M 。我如何存档?

    任何帮助都会很好,提前感谢。

    2 回复  |  直到 11 年前
        1
  •  4
  •   Community Mohan Dere    9 年前

    实际上,在多个层中存在一些开销。1Gbits/sec以太网在应用端并不意味着太多(但我想最多占90%)。经验法则是 send recv 相当大的数据大小(例如,至少几千字节)。发送或接收几百字节是低效的。这个问题肯定是特定于操作系统的(我想到的是Linux)。

    回想一下,根据定义,TCP不是数据包的传输,而是字节流的传输。阅读 TCP 维基页面。你应该避免 邮寄 -ing或 记录 -甚至是几百个字节。尝试 邮寄 每次数千字节。当然,一张单曲 记录 在接收端不(通常)对应于单个 邮寄 在发送端,反之亦然(特别是如果在发送和接收计算机之间有一些路由器;路由器可以拆分或合并网络数据包,因此不能确定是否有一个 记录 每个受体上 邮寄 在发射器中)。

    Gigabit Ethernet 欲望 Jumbo Frames 近9000字节。您可能需要数据缓冲区 邮寄 因为IP和TCP的各种开销),所以尝试8KB。

    这个 send(2) 手册页提及 MSG_MORE 标志 tcp(7) 。你可以小心使用。另请参见 this .

    而且 syscalls(2) 有一些开销。我很惊讶你能每秒制作一百万个。这一开销是将传出和传入数据缓冲为有效数据段(例如,每个数据段为8192、16384或32768字节;您需要进行基准测试以找到最佳数据段)的另一个原因。如果内核更喜欢页面对齐的数据,我不会感到惊讶。因此,也许可以尝试将缓冲区调整为4096字节(例如,使用 mmap(2) posix_memalign(3) ...)

    如果您关心性能,请不要使用 发送(2) 具有小字节计数。至少将应用程序更改为每次发送超过几千字节(例如4K字节) 邮寄 系统调用。对于 recv(2) ,传递至少4kilobytes的缓冲区。所以 邮寄 ing或 记录 单个字节或一百字节的行是低效的。您的应用程序应该缓冲这样的数据(并可能将数据拆分为“应用程序消息”…) 0MQ …),或至少使用分隔符(可能是换行符)终止每个消息,这将简化将接收到的缓冲区拆分为 几个 传入的应用程序消息。

    我的感觉是,您的应用程序效率低下且有问题(可能在其他网络上工作不好,例如,如果两台计算机之间都有一些路由器)。你需要 重新设计 并重新编写应用程序的某些部分!您需要缓冲,并且需要管理应用程序消息——拆分和连接它们。。。。

    你应该在多个网络上测试你的应用程序,特别是通过ADSL和wifi,如果可能的话,还可以通过远程网络(然后你会观察到 邮寄 记录 不“匹配”)。

        2
  •  2
  •   Dietrich Epp    11 年前

    根据我的计算,你相对接近饱和链接。

    据我所知,这是一秒钟的交通。

    Time              -------------traffic------------
    Time               bytin  bytout   pktin  pktout
    06/09/14-23:12:57  63.4M  155.3M  954.6K  954.6K
    

    通过以太网发送的TCP数据包有82个字节的开销(42个以太网,20个IP,20个TCP),因此接收的数据量为(954.6k*80+63.4M)*8位,总计1.1G。

    我假设,对于如此大量的数据包,物理介质的协商将涉及额外的开销。由于链路的利用率约为50%,如果有一个小到(1s/954.6k)*50%=500ns(半微秒!)的额外延迟,那么您已经考虑了额外的延迟。500纳秒是光传播150米所需的时间,这并不远。