【Socket網絡編程】connect函數超時處理

參考鏈接:Linux下connect超時處理【總結】

1、前言

  最近在寫一個測試工具,要求快速的高效率的掃描出各個服務器開放了哪些端口。當時想了一下,ping只能檢測ip,判斷服務器的網絡是連通的,而不能判斷是否開放了端口。我們知道端口屬於網絡的傳輸層,因此需要用ip和端口來探測,這個時候就可以用connect來探測一下,針對TCP協議,connect函數要進行TCP三次握手,如果connect成功,則說明服務器開放了某個端口,如果connect失敗,則說明服務器沒有開放某個端口。而connect失敗是通過超時來控制的,在規定的時間內,connect會發起多次連接,一直執行到超時,才返回錯誤。默認情況下,connect是阻塞的,而且默認的超時時間爲75s(系統內核決定),正常情況下,檢測網絡的連通性都是毫秒級,如果要判斷10萬臺服務器的,用阻塞的默認的connect去做,效率非常低下。因此採用非阻塞的connect,而且需要自定義超時間(我自定義超時時間爲5s)。

2、非阻塞connect

  對於阻塞式套接字,調用connect函數將激發TCP的三次握手過程,而且僅在連接建立成功或者出錯時才返回;對於非阻塞式套接字,如果調用connect函數會之間返回-1(表示出錯),且錯誤爲EINPROGRESS,表示連接建立,建立啓動但是尚未完成;如果返回0,則表示連接已經建立,這通常是在服務器和客戶在同一臺主機上時發生。

  select是一種IO多路複用機制,它允許進程指示內核等待多個事件的任何一個發生,並且在有一個或者多個事件發生或者經歷一段指定的時間後才喚醒它。connect本身並不具有設置超時功能,如果想對套接字的IO操作設置超時,可使用select函數。

  對於select和非阻塞connect,注意兩點:[1] 當連接成功建立時,描述符變成可寫; [2] 當連接建立遇到錯誤時,描述符變爲即可讀,也可寫,遇到這種情況,可調用getsockopt函數。

3、實現步驟

(1) 創建socket,並利用fcntl將其設置爲非阻塞

(2) 調用connect函數,如果返回0,則連接建立;如果返回-1,檢查errno ,如果值爲 EINPROGRESS,則連接正在建立。

(3) 爲了控制連接建立時間,將該socket描述符加入到select的可讀可寫集合中,採用select函數設定超時。

(4) 如果規定時間內成功建立,則描述符變爲可寫;否則,採用getsockopt函數捕獲錯誤信息

(5) 恢復套接字的文件狀態並返回

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章