SO_REUSEADDR作用
来源:互联网 发布:c语言第三章答案 编辑:程序博客网 时间:2024/05/03 17:59
tcp/ip详解的卷1有详细介绍过tcp的相关内容,其中TIME_WAIT讲得有点晦涩,今日找到一篇不错的文章,特拿来分享一下。
netstat-n | awk '/^tcp/ {++state[$NF]} END {for(key in state) printkey,"/t",state[key]}'
会得到类似下面的结果,具体数字会有所不同:
LAST_ACK 1
SYN_RECV14
ESTABLISHED79
FIN_WAIT128
FIN_WAIT23
CLOSING 5
TIME_WAIT1669
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
也就是说,这条命令可以把当前系统的网络连接状态分类汇总。
下面解释一下为啥要这样写:
一个简单的管道符连接了netstat和awk命令。
------------------------------------------------------------------
每个TCP报文在网络内的最长时间,就称为MSL(MaximumSegment Lifetime),它的作用和IP数据包的TTL类似。
RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。
注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务
器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。
举例:
1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的
80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。
2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连
接还处于TIME_WAIT状态。
检查net.ipv4.tcp_tw当前值,将当前的值更改为1分钟:
[root@aaa1~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse= 0
net.ipv4.tcp_tw_recycle= 0
[root@aaa1~]#
vi/etc/sysctl
增加或修改net.ipv4.tcp_tw值:
net.ipv4.tcp_tw_reuse= 1
net.ipv4.tcp_tw_recycle= 1
使内核参数生效:
[root@aaa1~]# sysctl -p
[root@aaa1~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse= 1
net.ipv4.tcp_tw_recycle= 1
用netstat再观察正常
这里解决问题的关键是如何能够重复利用time_wait的值,我们可以设置时检查一下time和wait的值
#sysctl-a | grep time | grep wait
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait= 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait= 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait= 120
问一下TIME_WAIT有什么问题,是闲置而且内存不回收吗?
是的,这样的现象实际是正常的,有时和访问量大有关,设置这两个参数:reuse是表示是否允许重新应用处于TIME-WAIT状态的
socket用于新的TCP连接;recyse是加速TIME-WAIT sockets回收
Q:我正在写一个unix server程序,不是daemon,经常需要在命令行上重启它,绝大
多数时候工作正常,但是某些时候会报告"bind:address in use",于是重启失
败。
A:Andrew Gierth
server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。至于
TIME_WAIT状态,你无法避免,那是TCP协议的一部分。
Q:如何避免等待60秒之后才能重启服务
A: ErikMax Francis
使用setsockopt,比如
--------------------------------------------------------------------------
intoption = 1;
if (setsockopt ( masterSocket, SOL_SOCKET, SO_REUSEADDR, &option,
sizeof(option ) ) < 0 )
{
die("setsockopt" );
}
--------------------------------------------------------------------------
Q: 编写TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?
A:这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用
端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,
指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧
使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期
望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不
可能。
一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端
口。SO_REUSEADDR仅仅表示可以重用本地本地地址、本地端口,整个相关五元组
还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使
用SO_REUSEADDR 选项。
Q:在客户机/服务器编程中(TCP/SOCK_STREAM),如何理解TCP自动机 TIME_WAIT 状
态?
A: W.Richard Stevens <1999年逝世,享年49岁>
下面我来解释一下TIME_WAIT 状态,这些在<>
中2.6节解释很清楚了。
MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现
都必须选择一个确定的MSL值。RFC1122建议是2分钟,但BSD传统实现采用了30秒。
TIME_WAIT状态最大保持时间是2 * MSL,也就是1-4分钟。
IP头部有一个TTL,最大值255。尽管TTL的单位不是秒(根本和时间无关),我们仍需
假设,TTL为255的TCP报文在Internet上生存时间不能超过MSL。
TCP报文在传送过程中可能因为路由故障被迫缓冲延迟、选择非最优路径等等,结果
发送方TCP机制开始超时重传。前一个TCP报文可以称为"漫游TCP重复报文",后一个
TCP报文可以称为"超时重传TCP重复报文",作为面向连接的可靠协议,TCP实现必须
正确处理这种重复报文,因为二者可能最终都到达。
一个通常的TCP连接终止可以用图描述如下:
clientserver
FINM
close-----------------> (被动关闭)
ACKM+1
<-----------------
FINN
<-----------------close
ACKN+1
----------------->
为什么需要TIME_WAIT 状态?
假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发
最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连
接的两个方向(全双工关闭),client必须进入TIME_WAIT 状态,因为client可能面
临重发最终ACK的情形。
{
scz2001-08-31 13:28
先调用close()的一方会进入TIME_WAIT状态
}
此外,考虑一种情况,TCP实现可能面临先后两个同样的相关五元组。如果前一个连
接处在TIME_WAIT 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理
TCP报文时,两个连接互相干扰。使用SO_REUSEADDR 选项就需要考虑这种情况。
为什么TIME_WAIT 状态需要保持 2MSL 这么长的时间?
如果TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。
第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二
个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT
状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被
丢弃。建立第二个连接的时候,不会混淆。
A:小四
在Solaris7下有内核参数对应 TIME_WAIT 状态保持时间
# ndd-get /dev/tcp tcp_time_wait_interval
240000
# ndd-set /dev/tcp tcp_time_wait_interval 1000
缺省设置是240000ms,也就是4分钟。如果用ndd修改这个值,最小只能设置到1000ms,
也就是1秒。显然内核做了限制,需要KernelHacking。
# echo"tcp_param_arr/W 0t0" | adb -kw /dev/ksyms /dev/mem
physmem3b72
tcp_param_arr:0x3e8 = 0x0
# ndd-set /dev/tcp tcp_time_wait_interval 0
我不知道这样做有什么灾难性后果,参看<>的声明。
Q:TIME_WAIT 状态保持时间为0会有什么灾难性后果?在普遍的现实应用中,好象也
就是服务器不稳定点,不见得有什么灾难性后果吧?
D:rain@bbs.whnet.edu.cn
Linux内核源码 /usr/src/linux/include/net/tcp.h 中
#defineTCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
* closethe socket, about 60 seconds */
最好不要改为0,改成1。端口分配是从上一次分配的端口号+1开始分配的,所以一般
不会有什么问题。端口分配算法在tcp_ipv4.c中tcp_v4_get_port中。
源文档 <http://blog.csdn.net/hairetz/archive/2009/09/09/4537158.aspx>
- SO_REUSEADDR作用
- SO_REUSEADDR作用
- SO_REUSEADDR的作用
- SO_REUSEADDR 的作用
- SO_REUSEADDR的作用
- SO_REUSEADDR的作用
- SO_REUSEADDR的作用
- SO_REUSEADDR 套接字选项作用
- SO_REUSEADDR
- SO_REUSEADDR
- SO_REUSEADDR
- SO_REUSEADDR
- SO_REUSEADDR
- SO_REUSEADDR
- SO_REUSEADDR在Linux和Windows的区别SO_LINGER的作用
- SO_REUSEADDR例解
- SO_REUSEADDR例解
- SO_REUSEADDR例解
- 为datagrid单元格增加渲染效果的简单方法
- 汉字转化成拼音 汉字转化成拼音
- English -Learning1
- 虚拟机linux下挂载本地硬盘
- test
- SO_REUSEADDR作用
- 开源JMS服务器-openJms介绍
- 外公的土屋
- QT 4.7.1 vs2010 x64 编译
- 风雨20年:我所积累的20条编程经验
- 近期目标
- c格式化输出
- SSH基于密钥验证的配置方法
- 【 �最珍贵的东西