网络服务器常见问题及处理

声明:本文原内容来自 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:是真是存在的一个缓冲区,是包在下行过程中,实际存在的一个缓冲区。

所以对txqueuelen的设置应该根据wmem大小增大,以保证使用wmem来控制发送缓冲区,以保证可以通过sendto失败来监控到缓冲区满的情况。
txqueuelen > (wmem / (包大小 + 250)) * socket数, 如一个网卡仅有一个发送socket,设置wmem=1M, 将txqueuelen设置为1w
设置方法:
ifconfig eth1 txqueuelen 10000
设置后立即生效,不需要重启进程

三、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。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值