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

套接字编程的缓冲区大小是多少?

  •  27
  • uriDium  · 技术社区  · 14 年前

    我们正在使用.NET和套接字。服务器正在使用socket.sender(bytes[])方法,因此它只发送整个负载。另一方面,我们是使用数据的客户。socket.receive(缓冲区[])。在所有来自微软(和其他公司)的例子中,他们似乎都坚持使用8192的缓冲区大小。我们已经使用了这个大小,但是偶尔我们会向超过这个缓冲区大小的客户机发送数据。

    有没有一种方法可以确定服务器的发送方法向我们发送了多少数据?最好的缓冲区大小是多少?

    5 回复  |  直到 6 年前
        1
  •  36
  •   Jon Skeet    14 年前

    即使您发送的数据比这多,它也可能无法在一次通话中接收。

    您无法确定服务器发送了多少数据-这是一个 流动 一次只读取数据块。你可以阅读 部分 服务器在一次发送呼叫中发送的数据,或者您可以在一次接收呼叫中从两次发送呼叫中读取数据。8K是一个合理的缓冲区大小-不太大,会浪费大量内存,也不太小,以至于需要使用大量浪费的接收调用。4K或16K也可能很好…对于网络缓冲区,我个人不会超过16K——我怀疑你很少填满它们。

    您可以尝试使用一个非常大的缓冲区,并记录每个调用中接收到的字节数,这可以让您了解一般情况下接收到的字节数。 可获得的 -但它不会真正显示使用较小缓冲区的效果。对于使用8K缓冲区,您有什么顾虑?如果是性能问题,您是否有证据表明代码的这一方面是性能瓶颈?

        2
  •  12
  •   antiduh    8 年前

    不幸的是,乔恩·斯基特的回答留下了很大一部分图片——发送缓冲区大小,以及 bandwidth-delay product 你要写信的管道。

    如果试图使用单个套接字通过大型管道发送数据,并且希望TCP填充该管道,则需要使用与管道的带宽延迟积相等的发送缓冲区大小。否则,TCP将不会填充管道,因为它在任何时候都不会留下足够的“字节在传输中”。

    考虑一个速度为千兆的连接,平均单向延迟为10毫秒。往返时间(也就是说,从发送数据包的套接字到接收该数据包的ACK从而知道发送更多数据所花费的时间)通常是延迟的两倍。

    因此,如果您有一个1千兆位的连接,并且RTT是20毫秒,那么这个管道在任何时候都有1千兆位/秒*20毫秒==2.5兆字节的数据在运行,如果它被完全利用的话。

    如果您的TCP发送缓冲区小于2.5兆字节,那么一个套接字将永远无法充分利用管道—您将永远无法从套接字中获得千兆/秒的性能。

    如果您的应用程序使用多个套接字,那么所有TCP发送缓冲区的总大小必须为2.5 MB,以便充分利用这个假设的1 Gigabit/20 ms RTT管道。例如,如果使用8192字节缓冲区,则需要306个同时TCP套接字来填充该管道。

        3
  •  7
  •   Justin Ethier    14 年前

    这取决于你的礼仪。如果您希望消息超过8192字节,那么应该相应地增加缓冲区大小。但请记住,这个缓冲区大小只适用于一个调用 Receive . 如果你真的想/需要,你可以循环 接收 多次将接收到的数据复制到任意大的数据结构或缓冲区中。

    还要记住,打电话是个好习惯 接收 重复,直到您验证已读取给定消息的所有数据;即使单个消息小于缓冲区大小,也可能无法通过单个消息检索所有数据。 接收 打电话。

        4
  •  0
  •   ckv    14 年前

    8192是理想的。如果您有超过这个大小的数据,您最好以固定长度的数据包发送数据。

    服务器发送的数据的大小可以使用winsock中的recv函数进行检查,该函数有一个给定缓冲区长度的参数。

        5
  •  0
  •   Robert Å pendl    6 年前

    不是微软相关的,但我只是在试用TCP端口(不是UNIX域套接字)来实现吞吐量。对具有不同缓冲区大小的4M输入进行计时,得出以下结果:

    1024 - real 0m0,102s; user  0m0,018s; sys   0m0,009s
    2048 - real 0m0,112s; user  0m0,017s; sys   0m0,009s
    8192 - real 0m0,163s; user  0m0,017s; sys   0m0,007s
     256 - real 0m0,101s; user  0m0,019s; sys   0m0,008s
      16 - real 0m0,144s; user  0m0,016s; sys   0m0,010s
    

    似乎在1024字节块中读取可以减少TCP开销,而处理时间(只是回显输入)不受缓冲区大小的影响。8192字节看起来很高,而真正的低值(如16)也不好。