socket中的SO_REUSEADDR
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)

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

http://blog.sina.com.cn/s/blog_53a2ecbf010095db.html

解析:SO_REUSEADDR bind: address in use的更多相关文章

  1. 解决bind错误 bind: Address already in use

    关于bind错误的处理: bind: Address already in use 原因: 操作系统没有立即释放端口 解决一: 等待一段时间运行网络程序即可 解决二:通过setsockopt进行设置, ...

  2. bind:Address alreasy is use

    在bind邦定时,通常会出现bind:Address alreasy is use错误. 此错误可以用setsockopt函数避免 int setsockopt(int sockfd,int leve ...

  3. bind: address already in use

    2016/04/18 09:46:06 server.go:36: listen at 0.0.0.0:9530 2016/04/18 09:46:06 server.go:39: listen er ...

  4. ipv4、ipv6的socket同时监听“bind: Address already in use”的解决方法

    创建ipv4和ipv6的socket,同时监听某个端口的ipv4和ipv6报文,运行时bind函数执行失败,提示“bind: Address already in use”.原因:ipv6的socke ...

  5. 报错处理——# Creating Server TCP listening socket *:6379: bind: Address already in use

    在启动redis时报错 # Creating Server TCP listening socket *:6379: bind: Address already in use 错误原因 6379地址已 ...

  6. 开启redis-server提示 # Creating Server TCP listening socket *:6379: bind: Address already in use--解决方法

    在bin目录中开启Redis服务器,完整提示如下: 3496:C 25 Apr 00:56:48.717 # Warning: no config file specified, using the  ...

  7. probably another instance of uWSGI is running on the same address (127.0.0.1:9090). bind(): Address already in use

    probably another instance of uWSGI is running on the same address (127.0.0.1:9090). bind(): Address ...

  8. 阿里云:uwsgi--配置出错 bind(): Address already in use [core/socket.c line 769]

    按照网上配置nginx+uwsgi+django的文章,nginx启动成功,django启动也成功,单独用uwsgi --http :8000 命令启动uwsgi也成功.使用uwsgi  --sock ...

  9. probably another instance of uWSGI is running on the same address (127.0.0.1:9090). bind(): Address ...

    probably another instance of uWSGI is running on the same address (127.0.0.1:9090). bind(): Address ...

随机推荐

  1. 在asp.net中执行存储过程(转)

    摘自:http://www.cnblogs.com/smhy8187/articles/677742.html 声明:本例用的数据库是系统提供的pubs数据库,表是是employee,编程语言用C# ...

  2. webview使用遇到 It is possible that this object was over-released, or is in the process of deallocation错误的解决办法

    使用wekwebview时,push后,再pop返回,报错了: Cannot form weak reference to instance (xxxx) of class xxxx. It is p ...

  3. 如何解决普通用户使用sudo找不到命令

    一.在linux的普通用户下,要使用root权限的命令需要使用sudo [dev@dev1 client_api]# sudo git pull origin develop sudo: git: c ...

  4. NYOJ-------笨蛋难题四

    笨蛋难题四 时间限制:1000 ms  |           内存限制:65535 KB 难度:3   描述 这些日子笨蛋一直研究股票,经过调研,终于发现xxx公司股票规律,更可喜的是 笨蛋推算出这 ...

  5. 迪杰斯特拉Dijkstra算法介绍

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...

  6. linux文件系统管理的工作原理

    一.系统在初始化时如何识别硬盘 1.系统初始时根据MBR的信息来识别硬盘,其中包括了一些执行文件就来载入系统,这些执行文件就是MBR里前面446bytes里的boot loader 程式,而后面的16 ...

  7. Smarty中{literal}的使用详解(ecshop)

    如何在文件里加入JS代码,如果按一般平常添加方法,会出错,解决的方法:把script套在{literal}{/literal}之间试试看,例如:{literal} {/literal} ------- ...

  8. Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)

    关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...

  9. Oracle学习笔记之六(DDL:表、索引、视图、同义词、序列操作相关SQL)

    下面这些基本的SQL语句应该熟悉,能够灵活运用.最好在不查资料的情况下,能够写出如下的任何代码. 1. 数据表操作相关 --创建表 create table STUDENTS( STUNO ) not ...

  10. 【转】SQL SERVER 获取存储过程返回值

    1.OUPUT参数返回值 CREATE PROCEDURE [dbo].[nb_order_insert]( @o_buyerid int , @o_id bigint OUTPUT ) AS BEG ...