網路程式設計之非阻塞socket的連線

2021-07-13 09:41:28 字數 2060 閱讀 8583

補充關於select在非同步(非阻塞)connect中的應用,剛開始搞socket程式設計的時候

我一直都用阻塞式的connect,非阻塞connect的問題是由於當時搞proxy scan

而提出的呵呵

通過在網上與網友們的交流及查詢相關faq,總算知道了怎麼解決這一問題.同樣

用select可以很好地解決這一問題.大致過程是這樣的:

1.將開啟的socket設為非阻塞的,可以用fcntl(socket, f_setfl, o_ndelay)完

成(有的系統用fnedlay也可).

2.發connect呼叫,這時返回-1,但是errno被設為einprogress,意即connect仍舊

在進行還沒有完成.

3.將開啟的socket設進被監視的可寫(注意不是可讀)檔案集合用select進行監視,

如果可寫,用

getsockopt(socket, sol_socket, so_error, &error, sizeof(int));

來得到error的值,如果為零,則connect成功.

在許多unix版本的proxyscan程式你都可以看到類似的過程,另外在solaris精華

區->程式設計技巧中有乙個通用的帶超時引數的connect模組.

我們知道,預設狀態下的套接字都是阻塞方式的,這意味著乙個套介面的呼叫不能立即完成時,程序將進入睡眠狀態,並等待操作完成。對於某些應用,需要及時可控的客戶響應,而阻塞的方式可能會導致乙個較長的時間段內,連線沒有響應。造成套接字阻塞的操作主要有recv, send, accept, connect.

下面主要以connect為例,講講非阻塞的connect的工作原理。當乙個tcp套接字設定為非阻塞後,呼叫connect,會立刻返回乙個einprocess的錯誤。但tcp的三路握手繼續進行,我們將用select函式檢查這個連線是否建立成功。建立非阻塞的connect有下面三個用途:

1.       可以在系統做三路握手的時候做些其它事情,這段時間你可以為所欲為。

2.       可以用這個技術同時建立多個連線,在web應用中很普遍。

3.       可以縮短connect的超時時間,多數實現中,connect的超時在75秒到幾分鐘之間,累傻小子呢?

雖然非阻塞的conncet實現起來並不複雜,但我們必須注意以下的細節:

* 即使套接字是非阻塞的,如果連線的伺服器是在同一臺主機,connect通常會立刻建立。(connect 返回 0 而不是 einprocess)

* 當連線成功建立時,描述字變成可寫

* 當連線出錯時,描述字變成可讀可寫

例程:定義乙個非阻塞的 connect 函式 connect_nonb

int connect_nonb(int sockfd, const sa *saptr, socklen_t salen, int nsec)

if(fd_isset(sockfd, &rset) || fd_isset(sockfd, &west))

else err_quit(「select error: sockfd  not set」);

done:

fcntl(sockfd, f_setfl, flags); // 恢復socket 屬性

if (error)

return (0);

}注意事項:

* 如果select呼叫之前,連線已經建立成功,並且有資料傳送過來了,這時套接字將是即可讀又可寫,和連線失敗時是一樣的。所以我們必須用getsockopt來檢查套接字的狀態。

* 如果我們不能確定套接字可寫是成功的唯一情況時,我們可以採用以下的呼叫

(1) 呼叫getpeername,如果呼叫失敗,返回enotconn,表示連線失敗

(2) 呼叫read,長度引數為0,如果read失敗,表示connect失敗。

(3) 再呼叫connect一次,其應該失敗,如果錯誤是eisconn,表示套接字已建立而且連線成功。

* 如果在乙個阻塞的套接字上呼叫的connect,在tcp三路握手前被中斷,如果connect不被自動重啟,會返回eintr。但是我們不能呼叫connect等待連線完成,這樣會返回eaddrinuse,此時我們必須呼叫select,和非阻塞的方式一樣。

網路程式設計之阻塞與非阻塞的理解

linux網路程式設計中 connect,send,recv 關於阻塞與非阻塞的理解 1,send,recv如果非阻塞,會立即返回,但每次返回的結果是不確定的,有可能一次傳送或者接收完成 也有可能需要多次,所以需要在乙個迴圈中,多次傳送或者接收,直到資料傳送或者接收完畢。2,send,recv如果阻...

非阻塞socket程式設計

socket程式設計中可能出現阻塞的呼叫有4個 1.write send sendto sendmsg sendv等,如果某個程序呼叫乙個阻塞的tcp套接字 預設設定 如果傳送緩衝區沒有空間,呼叫程序將會睡眠,直到有空間為止。如果tcp套接字是非阻塞的,且沒有空間可寫,則會返回乙個ewouleblo...

非阻塞socket程式設計

阻塞 阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。該程序被標記為睡眠狀態並被排程出去。函式只有在得到結果之後才會返回。當socket工作在阻塞模式的時候,如果沒有資料的情況下呼叫該函式,則當前執行緒就會被掛起,直到有資料為止。非阻塞 非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前,該函式不...