Linux(程序设计):48---缓冲区大小(SO_RCVBUF、SO_SNDBUF套接字选项)
套接字选项详细介绍,见文章:https://blog.csdn.net/qq_41453285/article/details/89536443一、选项简单介绍当使用setsockopt来设置TCP的接收缓冲区和发送缓冲区的大小时,系统都会将其值加倍,并且不得小于某个最小值。TCP接收缓冲区的最小值是256字节(不同系统会有不同的值),而发送缓冲区的最小值是2048字节(不同系统会有不同的值...
·
一、选项简单介绍
- 当使用setsockopt来设置TCP的接收缓冲区和发送缓冲区的大小时,系统都会将其值加倍,并且不得小于某个最小值。TCP接收缓冲区的最小值是256字节(不同系统会有不同的值),而发送缓冲区的最小值是2048字节(不同系统会有不同的值)。系统这样做的目的主要是:确保一个TCP连接拥有足够的空闲缓冲区来处理拥塞(比如快速重传算法就期望TCP接收缓冲区能至少容纳4个大小为SMSS的TCP报文段)
- 此外,我们还可以直接修改内核参数/proc/sys/net/ipv4/tcp_rmem和/proc/sys/net/ipv4/tcp_wmem来强制TCP接收缓冲区和发送缓冲区的大小没有最小值限制
二、演示案例
客户端
- 客户端发送数据给服务端,并且设置了发送缓冲区的大小(大小由程序参数传入),设置完之后打印一下设置的缓冲区大小
//cli_send.c #include <sys/socket.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <libgen.h> #define BUFFER_SIZE 512 int main( int argc, char* argv[] ) { if( argc <= 3 ) { printf( "usage: %s ip_address port_number send_bufer_size\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); struct sockaddr_in server_address; bzero( &server_address, sizeof( server_address ) ); server_address.sin_family = AF_INET; inet_pton( AF_INET, ip, &server_address.sin_addr ); server_address.sin_port = htons( port ); int sock = socket( PF_INET, SOCK_STREAM, 0 ); assert( sock >= 0 ); int sendbuf = atoi( argv[3] ); int len = sizeof( sendbuf ); setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) ); getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len ); printf( "the tcp send buffer size after setting is %d\n", sendbuf ); if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 ) { char buffer[ BUFFER_SIZE ]; memset( buffer, 'a', BUFFER_SIZE ); send( sock, buffer, BUFFER_SIZE, 0 ); } close( sock ); return 0; }
服务端
- 服务端接收客户端的数据,并且设置了接收缓冲区的大小(大小由程序参数传入),设置完之后打印一下设置的缓冲区大小
//ser_recv.c #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <libgen.h> #define BUFFER_SIZE 1024 int main( int argc, char* argv[] ) { if( argc <= 3 ) { printf( "usage: %s ip_address port_number receive_buffer_size\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int sock = socket( PF_INET, SOCK_STREAM, 0 ); assert( sock >= 0 ); int recvbuf = atoi( argv[3] ); int len = sizeof( recvbuf ); setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) ); getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len ); printf( "the receive buffer size after settting is %d\n", recvbuf ); int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( sock, 5 ); assert( ret != -1 ); struct sockaddr_in client; socklen_t client_addrlength = sizeof( client ); int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); if ( connfd < 0 ) { printf( "errno is: %d\n", errno ); } else { char buffer[ BUFFER_SIZE ]; memset( buffer, '\0', BUFFER_SIZE ); while( recv( connfd, buffer, BUFFER_SIZE-1, 0 ) > 0 ){} close( connfd ); } close( sock ); return 0; }
运行程序
- 运行服务端程序,将其接收缓冲区大小设置为50字节(但是输出的大小却是2304字节,说明此系统的TCP接收端缓冲区最小值为2304)
- 运行客户端程序,将其发送缓冲区大小设置为2304字节(但是输出的大小却是4608,这与缓冲区会被系统设置加倍的概念相符合)
更多推荐
已为社区贡献9条内容
所有评论(0)