socket对应的内核缓冲区(发送,接收)的大小

来源:互联网 发布:如何开淘宝网店代理 编辑:程序博客网 时间:2024/05/20 16:37

问题探讨:做一个小实验,需要把80K大的数据发送给另一方,当我在使用setsockopt()设置缓冲区的大小时,居然在设置到1024*1024时,也没返回SOCKET_ERROR,所以心里有点疑问,Socket的缓冲区是不是可以设置为任意大小呢?另外,如果缓冲区设置很大,如80*1024,那使用Send()一次性发送70K的数据,能够一次性就发送出去吗?


设置这个缓冲区,不是说一次就能发送多少数据,这个是窗口,滑动窗口,缓冲区和报文长度是不一样的,简单来说,报文是逻辑上不能分割的最小传输单元(因为物理上虽然可能允许分为多个片,但假如任意一个片丢失或有错,那么整个报文都要重传,所以说它是逻辑上不可分割的),每个网络都能设置允许通过的最大报文段大小。
缓冲区是发送端和接收端都有的,而且会有多个。我们知道TCP/IP协议是分层的,一层处理完再交给另一层处理,因此每层都有自己的缓冲区:网卡驱动有缓冲区、IP层有缓冲区、TCP/UDP层有缓冲区、同样应用层也必须有缓冲区。这些缓冲区都是为了接收相应的报文的。
所以不要把缓冲区和报文长度弄混了,你在程序中把缓冲区设大或设小,仅仅是设置一次能够暂存多少未处理的报文数据而已。你需要发送80K的数据,假如最大报文长度是1024,那么你仍然至少需要发送80个报文.

第一次接收27740个字节,只是说第一次时,TCP缓冲区中有不少于27740个字节的数据可以拿,因此应用程序先取了27740个字节来处理,第二次~第四次是一样的。
但这27740个字节具体是用多少个报文段发送过来的,就不得而知了。你也没办法通过设置应用程序的缓冲区大小来控制一次发送的报文段长度

注意,电脑存在缓冲区默认字节<一般为8K,可以通过setsockopt进行设定>,对于udp协议来说,如果发送数据包大小大于默认缓冲区大小的部分,在发送前会被丢弃,可以通过setsockopt结局这个问题.


一下文字转载自别人博客:

前面我们讲过内核缓冲区和应用程序缓冲区, 在本文中, 我们仅仅讨论内核缓冲区, 下面, 我们来看程序:

[cpp] view plain copy
  1. #include <winsock2.h>  
  2. #include <stdio.h>  
  3. #pragma comment(lib, "ws2_32.lib")  
  4.   
  5. int main()  
  6. {  
  7.     WORD wVersionRequested;  
  8.     WSADATA wsaData;  
  9.     wVersionRequested = MAKEWORD(1, 1);  
  10.     WSAStartup( wVersionRequested, &wsaData );  
  11.   
  12.   
  13.     SOCKET sockClient1 = socket(AF_INET, SOCK_STREAM, 0);  
  14.   
  15.     // 获取sockClient1对应的内核接收缓冲区大小  
  16.     int optVal = 0;  
  17.     int optLen = sizeof(optVal);  
  18.     getsockopt(sockClient1, SOL_SOCKET, SO_RCVBUF, (char*)&optVal, &optLen);  
  19.     printf("sockClient1, recv buf is %d\n", optVal); // 8192  
  20.   
  21.   
  22.     SOCKET sockClient2 = socket(AF_INET, SOCK_STREAM, 0);  
  23.   
  24.     // 设置sockClient2对应的内核接收缓冲区大小  
  25.     optVal = 1024;  
  26.     setsockopt(sockClient2, SOL_SOCKET, SO_RCVBUF, (char*)&optVal, optLen);  
  27.       
  28.   
  29.     // 再次获取sockClient1对应的内核接收缓冲区大小  
  30.     getsockopt(sockClient1, SOL_SOCKET, SO_RCVBUF, (char*)&optVal, &optLen);  
  31.     printf("sockClient1, recv buf is %d\n", optVal); // 8192  
  32.   
  33.   
  34.     // 获取sockClient2对应的内核接收缓冲区大小  
  35.     getsockopt(sockClient2, SOL_SOCKET, SO_RCVBUF, (char*)&optVal, &optLen);  
  36.     printf("sockClient2, recv buf is %d\n", optVal); // 1024  
  37.       
  38.   
  39.     while(1);  
  40.   
  41.   
  42.     closesocket(sockClient1);  
  43.     closesocket(sockClient2);  
  44.     WSACleanup();  
  45.   
  46.     return 0;  
  47. }  
      有3点值得说明:

      1. 上面我们仅仅写了接收的内核缓冲区, 关键字是SO_RCVBUF, 如果是发送的内核缓冲区, 那就用SO_SNDBUF, 有兴趣的童鞋可以稍微修改一下上面程序即可。

      2. 从程序的结果我们可以看到, sockClient1和sockClient2两者的发送内核缓冲区没有任何关系。

      3. 听一网友说过, tcp才有所谓的内核缓冲区, udp没有。


原文转载自:http://blog.csdn.net/stpeace/article/details/43777287

就本人验证,udp还是存在缓冲区的,直接上图.<并且存在默认值为8K>


原创粉丝点击