socket 缓冲区大小设置

来源:互联网 发布:阿里云网站空间购买 编辑:程序博客网 时间:2024/06/05 06:44
这几天都在写MUD服务器玩玩儿,在做SOCKET LIB封装类时,考虑到一个问题,对于大数据的接收是交由使用库的人来写while循环还是在库中就做好,后来又想到MUD只是发些字符串之类和简单的对角,是否一定要用到大数据,然后我就想了下,在windows环境下,对于WINSOCK1.1来说,默认的缓冲区最大长度为8K而对于WINSOCK2来说,最大的缓冲区是64K,然后我就写了个简单的客户端,发了超过64K的字节,原本以为这个字节发不出去应该会产生WSAEMSGSIZE,这个值是对于UDP的sendto而言的,我用的是TCP,就是为了测试下是不是也是这个值,但很明显,就是一个很大的值,大到什么程序?大到越过100K时也一样能正确发送出去,然后在接收部分,我也是用基于TCP的recv ,在这里,recv 只能接收到27.9K的数据,很明显,这个值不在8K到64K的空间,然后我用下面的代码取得缓冲区的大小
        unsigned   long   maxsize = 0;
        int size = sizeof(maxsize);
        getsockopt(dsock.GetSock(),SOL_SOCKET,SO_MAX_MSG_SIZE,(char*)&maxsize,&size);
结果返回的值是:4294967295
想了很久我也想不明白到底是怎么一回事!想看了MSDN关于O_MAX_MSG_SIZE的描述:
     Maximum   outbound   (send)   message   size   is   dependent   on   the   underlying   network   MTU   (maximum   sized   transmission   unit)   and   hence   cannot   be   known   until   after   a   socket   is   bound.   Applications   should   use   getsockopt   to   retrieve   the   value   of   SO_MAX_MSG_SIZE   after   the   socket   has   been   bound   to   a   local   address. 
MTU:MTU是Maximum Transmission Unit的缩写。意思是网络上传送的最大数据包。
最后,我认为SO_MAX_MSG_SIZE与SO_RCVBUF,   SO_SENDBUF没有什么太大关系。实际能够发送的的最大值与网络中的MTU值有关系。
而对于UDP,发包最大也只能一次发小于64K的包,其中包中必须还要有协议头文之类的东西,也就是说实际上的数据+协议才小于64K,
我对于UDP作了如下判断:
         udp包理论一般不要超过64k(实际上60k),如果数据包大于64k的话,就需要采用数据分包与接收端的重组技术。数据包越小,   掉包越小。并且前后发包需要一定延时,一般sleep(10),否则发送缓冲区会立即塞满,而后面发送的数据会丢掉。
但对于TCP如何呢?
        对基于消息的UDP来说,只能限制它的数据大小,但从上面得到的值来看,TCP的发送能力绝对是UDP远远不及的。
       在TCP协议中,大的数据实际上可能经过两次分割:第一次是TCP协议会把数据分段已装入一个TCP报文中,由于TCP报文将要被放入IP包中,所以每个分段<SO_MAX_MSG_SIZE; 第二次是IP包经过某物理时,如果IP包>该网络的MTU,那么IP协议会将该IP包切片;
以下这段是在网上的一个论坛上找到的描述:
     

Internet, 路由器可能会将MTU设为不同的值路由器可能会将MTU设为不同的值;

PPPoE/ADSL:1492
Dial Up/Modem:576

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的.   
这 个1500字节被称为链路层的MTU(最大传输单元).    根据四层网络拓扑结构, 扣除IP层中的包装字段(IP数据报的首部为20字节),所以IP数据报的数据区长度最大为1480字节, 而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的;另外考虑传输层UDP的首部占用8个字节,所以UDP数据报的数据区最大长度为1472字节.


很明显,就SO_MAX_MSG_SIZE这种,它可能更适合于UDP,对于TCP,它基本上是无能为力的.