Address already in use,在关闭进程后再次运行服务器bind时

2013年6月17日 由 Creater 留言 »

虽然用Ctrl+C强制结束了进程,但错误依然存在,用netstat -an |grep 5120和ps aux |grep 5120都还能看到刚才用Ctrl+C“强制结束”了的进程,端口还是使用中,只好每次用kill结束进程。
bind 普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind 返回 EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。
等待 TIME_WAIT 结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开 TIME_WAIT 状态。可以给套接字应用 SO_REUSEADDR 套接字选项,以便端口可以马上重用。
使用 SO_REUSEADDR 套接字选项避免地址使用错误

int sock, ret, on;
struct sockaddr_in servaddr;
/* Create a new stream (TCP) socket */
sock = socket( AF_INET, SOCK_STREAM, 0 ):
/* Enable address reuse */
on = 1;
ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
/* Allow connections to port 8080 from any available interface */
memset( &servaddr, 0, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( 45000 );
/* Bind to the address (interface/port) */
ret = bind( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) );

在应用了 SO_REUSEADDR 选项之后,bind API 函数将允许地址的立即重用。

SO_REUSEADDR 可以用在以下四种情况下。
( 摘自《 Unix 网络编程》卷一,即 UNPv1)
1 、当有一个有相同本地地址和端口的 socket1 处于 TIME_WAIT 状态时,而你启
动的程序的 socket2 要占用该地址和端口,你的程序就要用到该选项。
2 、 SO_REUSEADDR 允许同一 port 上启动同一服务器的多个实例 ( 多个进程 ) 。但
每个实例绑定的 IP 地址是不能相同的。在有多块网卡或用 IP Alias 技术的机器可
以测试这种情况。
3 、 SO_REUSEADDR 允许单个进程绑定相同的端口到多个 socket 上,但每个 soc
ket 绑定的 ip 地址不同。这和 2 很相似,区别请看 UNPv1 。
4 、 SO_REUSEADDR 允许完全相同的地址和端口的重复绑定。但这只用于 UDP 的
多播,不用于 TCP 。

广告位

发表评论

你必须 登陆 方可发表评论.