再談Bind()錯誤的解決

在以前的文章中,我曾經引用過一篇端口重用與端口獨佔程序設計。但是,後來我發現其中有一點寫的不清楚,爲清視聽,善意爲作者添加一點. setsockopt()中的第四個參數是端口重用與否的標誌,爲1則可重用,否則,禁止重用。所以,上面那篇文章應該加一句:cflag=1;


隱患 3.地址使用錯誤(EADDRINUSE)

您 可以使用 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 來禁止地址重用)。


清單 3.使用 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 函數將允許地址的立即重用。

文章來自於:blog.chinaunix.net/u/6163/showart.php
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章