socket中的so-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 3977344
  • 博文数量: 536
  • 博客积分: 10470
  • 博客等级: 上将
  • 技术积分: 4825
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-26 14:08
文章分类

全部博文(536)

文章存档

2024年(3)

2021年(1)

2019年(1)

2017年(1)

2016年(2)

2013年(2)

2012年(10)

2011年(43)

2010年(10)

2009年(17)

2008年(121)

2007年(252)

2006年(73)

分类:

2008-01-09 16:23:59

q: 我正在写一个unix server程序,不是daemon,经常需要在命令行上重启它,绝大多数时候工作正常,但是某些时候会报告"bind: address in use",于是重启失败。

a: andrew gierth
server程序总是应该在调用bind()之前设置so_reuseaddr套接字选项。至于time_wait状态,你无法避免,那是tcp协议的一部分。

q: 如何避免等待60秒之后才能重启服务

a: erik max francis
使用setsockopt,比如
--------------------------------------------------------------------------
int option = 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值。rfc 1122建议是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连接终止可以用图描述如下:

client server
fin m
close -----------------> (被动关闭)
ack m 1
<-----------------
fin n
<----------------- close
ack n 1
----------------->

为什么需要 time_wait 状态?

假设最终的ack丢失,server将重发fin,client必须维护tcp状态信息以便可以重发最终的ack,否则会发送rst,结果server认为发生错误。tcp实现必须可靠地终止连接的两个方向(全双工关闭),client必须进入 time_wait 状态,因为client可能面临重发最终ack的情形。

{
  先调用close()的一方会进入time_wait状态
}

此外,考虑一种情况,tcp实现可能面临先后两个同样的相关五元组。如果前一个连接处在 time_wait 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理tcp报文时,两个连接互相干扰。使用 so_reuseaddr 选项就需要考虑这种情况。

为什么 time_wait 状态需要保持 2msl 这么长的时间?

如果 time_wait 状态保持时间不足够长(比如小于2msl),第一个连接就正常终止了。第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二个连接。tcp实现必须防止某个连接的重复报文在连接终止后出现,所以让time_wait状态保持时间足够长(2msl),连接相应方向上的tcp报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不会混淆。

a: 小四

在solaris 7下有内核参数对应 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秒。显然内核做了限制,需要kernel hacking。

# echo "tcp_param_arr/w 0t0" | adb -kw /dev/ksyms /dev/memphysmem 3b72
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 中

#define tcp_timewait_len (60*hz) /* how long to wait to successfully* close the socket, about 60 seconds */

最好不要改为0,改成1。端口分配是从上一次分配的端口号 1开始分配的,所以一般不会有什么问题。端口分配算法在tcp_ipv4.c中tcp_v4_get_port中。

来源:
阅读(3557) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图