1 回答

TA貢獻1966條經驗 獲得超4個贊
以下是關于您的問題的一些想法:
您不能listen()
在同一個 IP+端口上使用多個ServerSocket
.?如果可以,操作系統會將 SYN 數據包傳輸到哪個套接字?*
TCP 確實維護了預先接受的連接的積壓,因此調用將accept()
(幾乎)立即返回積壓隊列中的第一個(最舊的)套接字。它通過自動發送 SYN-ACK 數據包來回復客戶端發送的 SYN,并等待回復 ACK(3 次握手)來實現。但是,正如@zero298 所建議的那樣,盡可能快地接受連接通常不是問題。問題將是處理與您將接受的所有套接字的通信所產生的負載,這很可能會使您的服務器崩潰(這實際上是一次 DoS 攻擊)。實際上這個參數通常在這里 太多并發連接在積壓隊列中等待太久backlog
accept()
在到達您的應用程序之前,ed 將被 TCP 丟棄。
我建議您使用ExecutorService
線程池來運行某個最大數量的線程,而不是為每個客戶端套接字創建一個線程,每個線程處理與一個客戶端的通信。這允許系統資源的優雅降級,而不是創建數百萬個線程,這反過來會導致線程饑餓、內存問題、文件描述符限制……再加上精心選擇的積壓值,您將能夠獲得您的服務器在不崩潰的情況下可以提供的最大吞吐量。run()
如果您擔心 SSL 上的 DoS,您的客戶端線程方法應該做的第一件事就是調用startHandshake()
新連接的套接字。
關于 SSL 部分,TCP 本身不能做任何 SSL 預接受,因為它需要執行加密/解碼、與密鑰庫對話等,這遠遠超出了它的規范。請注意,在這種情況下您還應該使用SSLServerSocket
。
積壓隊列用于 TCP 堆棧已完成但尚未被應用程序接受的連接。與 SSL 無關。JSSE 不會進行任何協商,直到您在已接受的套接字上執行一些 I/O,或在其上調用 startHandshake(),這兩者都將在處理連接的線程中執行。我看不出如何利用它制造 DOS 漏洞,至少不是特定于 SSL 的漏洞。如果您遇到 DOS 情況,很可能您正在 accept() 線程中執行本應在連接處理線程中完成的 I/O。
*:雖然Linux >=3.9 做了某種負載平衡,但僅適用于 UDP(所以不是?SSLServerSocket
)并且有選項SO_REUSEPORT
,這并不是在所有平臺上都可用。
添加回答
舉報