我在編寫服務端程序時,結束服務器端程序運行后,再次啟動程序,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 }