声明:本文原内容来自 http://hi.baidu.com/roxws/blog/item/1f57e52eea0ddc5c4fc226ac.html
一、UDP发送缓冲区,接收缓冲区,这个主要预防是网络抖动。
1. 默认udp socket的缓冲区由net.core.rmem_default决定(没有2倍等特殊关系),即rmem_default反映实际默认缓冲大小(注意不是rmem_max)
sk->sk_recbuf = sysctl_rmem_defaul;
sk->sk_sndbuf = sysctl_wmem_defaul;
2. net.core.rmem_default的配置不受net.core.rmem_max限制,实际效果也不受rmem_max限制, rmem_max只用于限制setsockopt
3. 程序自己通过setsockopt设置SO_RCVBUF时,设置的实际效果值为参数*2,且要求参数不超过rmem_max(超过时用rmem_max)
4. wmem_*与上相同
查看更多的内核源码,我们可以看到类似的情况也适用于SO_RCVBUF选项。如下面的一段摘录的代码:
427 case SO_RCVBUF:
428
432
433 if (val > sysctl_rmem_max)
434 val = sysctl_rmem_max;
435 set_rcvbuf:
436 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
437
452 if ((val * 2) < SOCK_MIN_RCVBUF)
453 sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
454 else
455 sk->sk_rcvbuf = val * 2;
456 break;
二、在设置rmem_default 同时,要设置txqueuelen。传输缓区长度大小。
rmem_default:是所有socket端口通用的。而通过 setsockopt 只设置当前端口。其实这个数字是表示一个端口上所有未发出的包所占的空间,并非真是描述某个缓冲区的。
txqueuelen:是真是存在的一个缓冲区,是包在下行过程中,实际存在的一个缓冲区。
三、tcp服务端设置
通用socket设置参看 http://hi.baidu.com/roxws/blog/item/e2958354bf32df58564e00c0.html
服务端要特别注意的是 time_wait问题。制定协议时,应该尽量让客户端先close。要注意:进程退出,tcp会主动发送结束符给对方。
#net.ipv4.tcp_tw_reuse = 1 对降低time_wait等待时间没有用处。测试没发现有什么用。这个应该主要是预防重启进程,提示端口已经被绑定的问题。
#net.ipv4.tcp_tw_recycle = 1 快速回收,降低time_wait等待时间。
设置socket的SO_LINGER选项: 这里要注意,如果有重发,会导致客户端增加重发次数。所以建议小心使用!!
此选项指定函数close对面向连接的协议如何操作(如TCP)。内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。
SO_LINGER选项用来改变此缺省设置。使用如下结构:
struct linger {
int l_onoff; /* 0 = off, nozero = on */
int l_linger; /* linger time */
};
有下列三种情况:
1、设置 l_onoff为0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据;
2、设置 l_onoff为非0,l_linger为0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;
3、设置 l_onoff 为非0,l_linger为非0,当套接口关闭时内核将拖延一段时间(由l_linger决定)。如果套接口缓冲区中仍残留数据,进程将处于睡眠状态,直 到(a)所有数据发送完且被对方确认,之后进行正常的终止序列(描述字访问计数为0)或(b)延迟时间到。此种情况下,应用程序检查close的返回值是非常重要的,如果在数据发送完并被确认前时间到,close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。close的成功返回仅告诉我们发送的数据(和FIN)已由对方TCP确认,它并不能告诉我们对方应用进程是否已读了数据。如果套接口设为非阻塞的,它将不等待close完成。
struct linger so_linger;
...
so_linger.l_onoff = TRUE;
so_linger.l_linger = 0;
z = setsockopt(s,
SOL_SOCKET,
SO_LINGER,
&so_linger,
sizeof so_linger);
rox认为最好tcp服务器设置方案:必须依靠客户端发送close,server不主动发送close!!!server只处理超时close和正常接收0字节的cloes。