2013-02-01 54 views
2

我正在使用select()進行非阻塞TCP套接字編程。如何阻止接受像真正的連接失敗?

後正常成立,

socket() 
make socket non-blocking 
bind() 
listen() 
FD_ZERO 
FD_SET 
    ... 
select() 

FD_ISSET 
    ... 
    s = accept() 

對於某些原因,服務器FD_ISSET之後做了一些準備,但隨後選擇不接受。簡單的方法就是在accept()後關閉s。但在accept()之前,有什麼方法可以告訴客戶端這個連接會失敗嗎?謝謝。

回答

3

不會。如果您收到一個傳入連接並且您不想要它,那麼您必須立即accept() is和close()。這不是TCP(或其他網絡協議)工作方式的結果,但它在套接字API中固有的

假設我們正在談論TCP/IP,注意到在select()(或poll()或其他)已通知您監聽套接字已準備好可供讀取的時候,已經太晚而無法接受連接:內核已經以您的名義接受了連接。也就是說,它已經發送了一個SYN|ACK來響應傳入的SYN數據包。這實際上是listen()系統調用的影響。之後,accept()的調用只是一種形式:它爲接受的連接分配一個新的文件描述符。

可以利用不同方式做事的最顯着的軟件是TCP wrappers。 TCP包裝器通常會決定是否僅接受基於遠程IP地址的傳入連接。如果有機會做出這個決定,並在它被接受之前拒絕連接,那麼它將使TCP連接被TCP封裝拒絕的客戶得到一個真正的「連接被拒絕」響應(對SYN數據包的RST響應,就像沒有任何人在港口上收聽一樣)。但是使用套接字接口,它沒有辦法做到這一點。相反,客戶端的連接被打開,然後立即關閉。

並非所有的操作系​​統都是這樣的。例如,在Cisco IOS上,當您配置vty端口上的訪問列表以允許來自某些IP地址的傳入連接並拒絕其他IP地址時,被拒絕的連接會得到一個真正的「連接被拒絕」。但它沒有使用套接字實現。 (它可能使用非常專有的東西來實現。)

+0

非常好的答案,非常感謝。 – user180574