1. 程式人生 > >對TCP埠和連線數的一點思考

對TCP埠和連線數的一點思考

先來看看一些約定俗成的內容。

  • 一個網絡卡對應一個IP地址
  • 一個IP地址對應65535個埠
  • 一個socket(addr, port)可以接受多個socket連線(accept)
  • 一個埠只能被一個socket監聽(listen)

我在面試的時候,被問到過這麼一個問題:ipv4協議下,假如主機的資源是無限的,理論上一個網絡卡能夠接受多少個tcp連線?這個問題一開始很容易有個naive的想法,連線數就和埠數一樣,65535。但這樣顯然是錯誤的,原因可以參考上面。

實際上這道題要文件本質是,一個tcp連線,必定有一個唯一區分這個連結的關鍵字。這顯然不是埠,而是(svr_addr, svr_port, cli_addr, cli_port, protocol)這麼一個五元組。理論上只要這五個值不完全一樣,就不是一個相同的連線。所以答案的數量級非常龐大。

ip能鎖定一臺物理機器,對應著一張網絡卡,外界發來的資料包網絡卡都會接收。但是問題來了,網絡卡給程式提供了介面,你監聽一下我,要是有訊息來了,我就轉發給你。這樣應用程式就能收到資料了。但是問題來了,程式A和程式B都需要監聽網絡卡接發資料,網絡卡說那我把接到的資料都發給你兩,你們自己看著辦吧。好,小A小B都接受了。但是又來了CDEF……,不行了,每個包都被髮到了所有應用程式,每個應用程式都累得不行,最終垮了。

好,那網絡卡說我給你們加個表示吧,我們之間可以用一個號碼來作為標識,我和小A之間就用1來標識,如果外界發給1號標識的資料我就轉發給你,你監聽我的時候得告訴我你監聽的時1,我就轉發1的資料包給你。好了其他的BCD…都自己弄一個標識號,只要不重複就行。這樣大家都省事了。

最後涉及到安全,一個標識號只能被一個應用程式監聽,因為如果小A程式和小B同時監聽一個標識號號,那就壞了,我傳的資料都被AB接到,這樣資料安全性就沒辦法保證了。

這個標識號就是埠,最初設計網路資料交換的設計者不知道是怎麼想的。這是我的理解。

其實網絡卡都是被系統層封裝了,埠和程序之間的關係也是系統封裝好的。我們只需要用socket就行,給定一個埠號就行了。其他的事都交給作業系統去做。

也就是說,假如沒有埠這麼一個東西,應用層的程式就只能夠直接監聽網絡卡,這樣會造成資源的浪費和很大的負荷,所以才劃分這麼多埠,並且一個埠只能被監聽一次。

實際上,埠的資訊只有到了TCP層才會被讀取(而不是在網絡卡、或者資料鏈路層等其他地方),所以在TCP層記錄了(port, pid)這麼一個二元組,表示某個port被pid監聽,從而讓資料段準確傳輸到正確的位置。