Linux socket默认值及setsockopt函数用法

来源:互联网 发布:诸葛亮七擒孟获 知乎 编辑:程序博客网 时间:2024/05/22 12:44


1. tcp 收发缓冲区默认值


[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_rmem  


4096    87380   4161536


87380  :tcp接收缓冲区的默认值


[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_wmem 


4096    16384   4161536


16384  : tcp 发送缓冲区的默认值


2. tcp 或udp收发缓冲区最大值


[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_max 


131071


131071:tcp 或 udp 接收缓冲区最大可设置值的一半。


也就是说调用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen);  时rcv_size 如果超过 131071,那么


getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等于 131071 * 2 = 262142


[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_max  


131071


131071:tcp 或 udp 发送缓冲区最大可设置值得一半。


跟上面同一个道理


3. udp收发缓冲区默认值


[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_default   


111616:udp接收缓冲区的默认值


[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_default 


111616


111616:udp发送缓冲区的默认值


4. tcp 或udp收发缓冲区最小值


tcp 或udp接收缓冲区的最小值为 256 bytes,由内核的宏决定;


tcp 或udp发送缓冲区的最小值为 2048 bytes,由内核的宏决定


本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-08/68874.htm


linux setsockopt函数的用法

1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:
BOOL bReuseaddr=TRUE;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));

2. 如果要已经处于连接状态的soket在调用closesocket后强制关闭,不经历
TIME_WAIT的过程:
BOOL bDontLinger = FALSE;
setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));

3.在send(),recv()过程中有时由于网络状况等原因,发收不能预期进行,而设置收发时限:
int nNetTimeout=1000;//1秒
//发送时限
setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));

4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节
(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中发送数据
和接收数据量比较大,可以设置socket缓冲区,而避免了send(),recv()不断的循环收发:
// 接收缓冲区
int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
//发送缓冲区
int nSendBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));

5. 如果在发送数据的时,希望不经历由系统缓冲区到socket缓冲区的拷贝而影响
程序的性能:
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));

6.同上在recv()完成上述功能(默认情况是将socket缓冲区的内容拷贝到系统缓冲区):
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));

7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:
BOOL bBroadcast=TRUE;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));

8.在client连接服务器过程中,如果处于非阻塞模式下的socket在connect()的过程中可
以设置connect()延时,直到accpet()被呼叫(本函数设置只有在非阻塞的过程中有显著的
作用,在阻塞的函数调用中作用不大)
BOOL bConditionalAccept=TRUE;
setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));

9.如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们
一般采取的措施是"从容关闭"shutdown(s,SD_BOTH),但是数据是肯定丢失了,如何设置让程序满足具体
应用的要求(即让没发完的数据发送出去后在关闭socket)?
struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff=1;//(在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
// 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;
m_sLinger.l_linger=5;//(容许逗留的时间为5秒)
setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));


端口复用的理解

在linux socket网络编程中,大规模并发TCP或UDP连接时,经常会用到端口复用:

 int opt = 1; if(setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *) &opt, sizeof(opt))){    perror("setsockopt");    return -1;}
  • 1
  • 2
  • 3
  • 4
  • 5

那么什么是端口复用呢,如何理解呢,可以解释成如下:
在A机上进行客户端网络编程,假如它所使用的本地端口号是1234,如果没有开启端口复用的话,它用本地端口1234去连接B机再用本地端口连接C机时就不可以,若开启端口复用的话在用本地端口1234访问B机的情况下还可以用本地端口1234访问C机。若是服务器程序中监听的端口,即使开启了复用,也不可以用该端口望外发起连接了。

SO_REUSEADDR和SO_REUSEPORT

SO_REUSEADDR提供如下四个功能:

SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的        本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址            即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即            可。这一般不用于TCP服务器。SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端            口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套            接口而言(TCP不支持多播)。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

SO_REUSEPORT选项有如下语义:

此选项允许完全重复捆绑,但仅在想捆绑相同IP地址和端口的套接口都指定了此套接口选项才行。如果被捆绑的IP地址是一个多播地址,则SO_REUSEADDR和SO_REUSEPORT等效。
  • 1
  • 2
  • 3
  • 4

使用这两个套接口选项的建议:

在所有TCP服务器中,在调用bind之前设置SO_REUSEADDR套接口选项;
  • 1
  • 2

当编写一个同一时刻在同一主机上可运行多次的多播应用程序时,设置SO_REUSEADDR选项,并将本组的多播地址作为本地IP地址捆绑。

setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&nOptval , sizeof(int)) < 0)

Q:编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?A:这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

原创粉丝点击