在進行linux網絡編程時,每次修改了源代碼並再次編譯運行時,常遇到下面的地使用錯誤:linux
Bind error: Address already in use編程
雖然用Ctrl+C強制結束了進程,但錯誤依然存在,用netstat -an |grep 5120和ps aux |grep 5120都還能看到剛纔用Ctrl+C「強制結束」了的進程,端口仍是使用中,只好每次用kill結束進程,非常麻煩。昨天晚上無心間瀏覽到IBM網站上 的一篇題爲《Linux 套接字編程中的 5 個隱患》的文章,恍然大悟,今天試了一下,果真解決問題,在此表示感謝,也但願更多的coder看到這篇文章,避免出錯。服務器
主要代碼爲:網絡
int on;socket
on = 1;
ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
如今我每次用Ctrl+C強制結束進程後,用netstat和ps都還能看到端口在使用中,但運行程序不會出現「Address already in use」的錯誤了,實現了端口的重用。函數
如下是原文中的第三個隱患--地址使用錯誤網站
地址使用錯誤(EADDRINUSE)code
您可使用 bind API 函數來綁定一個地址(一個接口和一個端口)到一個套接字端點。能夠在服務器設置中使用這個函數,以便限制可能有鏈接到來的接口。也能夠在客戶端設置中使用 這個函數,以便限制應當供出去的鏈接所使用的接口。bind 最多見的用法是關聯端口號和服務器,並使用通配符地址(INADDR_ANY),它容許任何接口爲到來的鏈接所使用。接口
bind 廣泛遭遇的問題是試圖綁定一個已經在使用的端口。該陷阱是也許沒有活動的套接字存在,但仍然禁止綁定端口(bind 返回 EADDRINUSE),它由 TCP 套接字狀態 TIME_WAIT 引發。該狀態在套接字關閉後約保留 2 到 4 分鐘。在 TIME_WAIT 狀態退出以後,套接字被刪除,該地址才能被從新綁定而不出問題。進程
等待 TIME_WAIT 結束多是使人惱火的一件事,特別是若是您正在開發一個套接字服務器,就須要中止服務器來作一些改動,而後重啓。幸運的是,有方法能夠避開 TIME_WAIT 狀態。能夠給套接字應用 SO_REUSEADDR 套接字選項,以便端口能夠立刻重用。
考慮清單 3 的例子。在綁定地址以前,我以 SO_REUSEADDR 選項調用 setsockopt。爲了容許地址重用,我設置整型參數(on)爲 1 (否則,能夠設爲 0 來禁止地址重用)。
使用 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 函數將容許地址的當即重用。
Linux 套接字編程中的 5 個隱患