首页 文章

socket编程有什么好的缓冲区大小?

提问于
浏览
28

我们正在使用.Net和套接字 . 服务器使用Socket.Sender(bytes [])方法,因此它只发送整个有效负载 . 另一方面,我们是消费数据的客户 . Socket.Receive(缓冲液[]) . 在Microsoft(和其他人)的所有示例中,他们似乎都坚持使用8192的缓冲区大小 . 我们已经使用了这个大小,但我们偶尔会向超出此缓冲区大小的客户端发送数据 .

有没有办法确定服务器发送方法发送给我们的数据量?什么是最好的缓冲区大小?

5 回答

  • 7

    即使您发送的数据多于此数据,也可能无法在一次调用Receive中使用 .

    您可以't determine how much data the server has sent - it'是一个数据流,而您一次只是在读取数据块 . 您可以阅读服务器在一个发送呼叫中发送的部分内容,或者您可以从一个接收呼叫中的两个发送呼叫中读取数据 . 8K是一个合理的缓冲区大小 - 没有那么大,你必须使用浪费的接收呼叫负载 . 4K或16K很可能也很好......我个人不会很少填写它们 .

    您可以通过尝试使用非常大的缓冲区并记录每次调用中接收到多少字节来进行实验 - 这可以让您了解通常可用的数量 - 但它不会有性能,您是否有任何证据表明这方面您的代码是性能瓶颈?

  • 0

    遗憾的是,Jon Skeet的答案留下了很大一部分 - 发送缓冲区大小,以及您正在写入的管道的bandwidth-delay product .

    如果您尝试使用单个套接字通过大型管道发送数据,并且您希望TCP填充该管道,则需要使用等于管道的带宽延迟乘积的发送缓冲区大小 . 否则,TCP将不会填充管道,因为它不会始终留下足够的“飞行中的字节” .

    考虑速度为1千兆位的连接,平均单向延迟为10毫秒 . 往返时间(也就是说,套接字发送数据包之间经过的时间和接收该数据包的确认时间因此知道发送更多数据的时间)通常是延迟的两倍 .

    因此,如果您拥有1千兆位连接,并且RTT为20毫秒,那么如果完全使用该管道,则该管道始终具有1千兆位/秒* 20毫秒== 2.5兆字节的数据 .

    如果您的TCP发送缓冲区小于2.5兆字节,那么一个套接字永远不会完全利用管道 - 您永远不会从套接字中获得千兆位/秒的性能 .

    如果您的应用程序使用多个套接字,则所有TCP发送缓冲区的聚合大小必须为2.5 MB,以便充分利用此假设的1千兆位/ 20毫秒RTT管道 . 例如,如果使用8192字节的缓冲区,则需要306个同时使用的TCP套接字来填充该管道 .

  • 36

    这取决于您的协议 . 如果您期望超过8192字节的消息,则应相应地增加缓冲区大小 . 但请记住,此缓冲区大小仅适用于对 Receive 的一次调用 . 如果您真的需要/需要,可以多次循环 Receive 并将接收到的数据复制到任意大的数据结构或缓冲区中 .

    另请注意,最好重复调用 Receive ,直到您确认已读取给定消息的所有数据为止;即使单个消息小于缓冲区大小,单个 Receive 调用仍然可能无法检索到所有消息 .

  • 0

    8192将是理想的 . 如果您的数据超过此大小,最好以恒定长度的数据包发送数据 .

    可以使用WINSOCK中的recv函数检查服务器发送的数据大小,该函数具有一个给出缓冲区长度的参数 .

  • 12

    不是微软有关系,但我只是尝试使用TCP端口(不是Unix域套接字)来查看吞吐量的C线程回显服务器 . 使用各种缓冲区大小对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)也不好 .

相关问题