我在编写服务端程序时,结束服务器端程序运行后,再次启动程序,bind函数就会返回address already in use这个错误,提示我端口已经被占用了。
使用 # netstat –apn | grep [port] 命令或者 lsof -i:[port] 命令查看端口的占用情况,可以发现之前被终止的服务器端程序进程仍在监听该端口。于是用kill命令杀掉再启动就可以正常运行了。后来在这篇文章找到了原因http://www.ibm.com/developerworks/cn/linux/l-sockpit/。
您可以使用 bind
API 函数来绑定一个地址(一个接口和一个端口)到一个套接字端点。可以在服务器设置中使用这个函数,以便限制可能有连接到来的接口。也可以在客户端设置中使用这个函数,以便限制应当供出去的连接所使用的接口。bind
最常见的用法是关联端口号和服务器,并使用通配符地址(INADDR_ANY
),它允许任何接口为到来的连接所使用。
bind
普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind
返回 EADDRINUSE
),它由 TCP 套接字状态 TIME_WAIT
引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT
状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。
等待 TIME_WAIT
结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开 TIME_WAIT
状态。可以给套接字应用 SO_REUSEADDR
套接字选项,以便端口可以马上重用。
在bind函数之前添加下面的代码即可解决问题。
1 int opt = 1; 2 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) != 0) 3 { 4 perror("Server setsockopt failed"); 5 return 1; 6 }