TCP IP和Socket的關係

2021-07-10 19:50:11 字數 3575 閱讀 1628

要寫網路程式就必須用socket,這是程式設計師都知道的。而且,面試的時候,我們也會問對方會不會socket程式設計?一般來說,很多人都會說,socket程式設計基本就是listen,accept以及send,write等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。

對於網路程式設計,我們也言必稱tcp/ip,似乎其它網路協議已經不存在了。對於tcp/ip,我們還知道tcp和udp,前者可以保證資料的正確和可靠性,後者則允許資料丟失。最後,我們還知道,在建立連線前,必須知道對方的ip位址和埠號。除此,普通的程式設計師就不會知道太多了,很多時候這些知識已經夠用了。最多,寫服務程式的時候,會使用多執行緒來處理併發訪問。

我們還知道如下幾個事實:

1。乙個指定的埠號不能被多個程式共用。比如,如果iis占用了80埠,那麼apache就不能也用80埠了。

2。很多防火牆只允許特定目標埠的資料報通過。

3。服務程式在listen某個埠並accept某個連線請求後,會生成乙個新的socket來對該請求進行處理。

於是,乙個困惑了我很久的問題就產生了。如果乙個socket建立後並與80埠繫結後,是否就意味著該socket占用了80埠呢?如果是這樣的,那麼當其accept乙個請求後,生成的新的socket到底使用的是什麼埠呢(我一直以為系統會預設給其分配乙個空閒的埠號)?如果是乙個空閒的埠,那一定不是80埠了,於是以後的tcp資料報的目標埠就不是80了--防火牆一定會組織其通過的!實際上,我們可以看到,防火牆並沒有阻止這樣的連線,而且這是最常見的連線請求和處理方式。我的不解就是,為什麼防火牆沒有阻止這樣的連線?它是如何判定那條連線是因為connet80埠而生成的?是不是tcp資料報裡有什麼特別的標誌?或者防火牆記住了什麼東西?

後來,我又仔細研讀了tcp/ip的協議棧的原理,對很多概念有了更深刻的認識。比如,在tcp和udp同屬於傳輸層,共同架設在ip層(網路層)之上。而ip層主要負責的是在節點之間(end to end)的資料報傳送,這裡的節點是一台網路裝置,比如計算機。因為ip層只負責把資料送到節點,而不能區分上面的不同應用,所以tcp和udp協議在其基礎上加入了埠的資訊,埠於是標識的是乙個節點上的乙個應用。除了增加埠資訊,upd協議基本就沒有對ip層的資料進行任何的處理了。而tcp協議還加入了更加複雜的傳輸控制,比如滑動的資料傳送視窗(slice window),以及接收確認和重發機制,以達到資料的可靠傳送。不管應用層看到的是怎樣乙個穩定的tcp資料流,下面傳送的都是乙個個的ip資料報,需要由tcp協議來進行資料重組。

所以,我有理由懷疑,防火牆並沒有足夠的資訊判斷tcp資料報的更多資訊,除了ip位址和埠號。而且,我們也看到,所謂的埠,是為了區分不同的應用的,以在不同的ip包來到的時候能夠正確**。

tcp/ip只是乙個協議棧,就像作業系統的執行機制一樣,必須要具體實現,同時還要提供對外的操作介面。就像作業系統會提供標準的程式設計介面,比如win32程式設計介面一樣,tcp/ip也必須對外提供程式設計介面,這就是socket程式設計介面--原來是這麼回事啊!

在socket程式設計介面裡,設計者提出了乙個很重要的概念,那就是socket。這個socket跟檔案控制代碼很相似,實際上在bsd系統裡就是跟檔案控制代碼一樣存放在一樣的程序控制代碼表裡。這個socket其實是乙個序號,表示其在控制代碼表中的位置。這一點,我們已經見過很多了,比如檔案控制代碼,視窗控制代碼等等。這些控制代碼,其實是代表了系統中的某些特定的物件,用於在各種函式中作為引數傳入,以對特定的物件進行操作--這其實是c語言的問題,在c++語言裡,這個控制代碼其實就是this指標,實際就是物件指標啦。

現在我們知道,socket跟tcp/ip並沒有必然的聯絡。socket程式設計介面在設計的時候,就希望也能適應其他的網路協議。所以,socket的出現只是可以更方便的使用tcp/ip協議棧而已,其對tcp/ip進行了抽象,形成了幾個最基本的函式介面。比如create,listen,accept,connect,read和write等等。

現在我們明白,如果乙個程式建立了乙個socket,並讓其監聽80埠,其實是向tcp/ip協議棧宣告了其對80埠的占有。以後,所有目標是80埠的tcp資料報都會**給該程式(這裡的程式,因為使用的是socket程式設計介面,所以首先由socket層來處理)。所謂accept函式,其實抽象的是tcp的連線建立過程。accept函式返回的新socket其實指代的是本次建立的連線,而乙個連線是包括兩部分資訊的,乙個是源ip和源埠,另乙個是宿ip和宿埠。所以,accept可以產生多個不同的socket,而這些socket裡包含的宿ip和宿埠是不變的,變化的只是源ip和源埠。這樣的話,這些socket宿埠就可以都是80,而socket層還是能根據源/宿對來準確地分辨出ip包和socket的歸屬關係,從而完成對tcp/ip協議的操作封裝!而同時,放火牆的對ip包的處理規則也是清晰明了,不存在前面設想的種種複雜的情形。

明白socket只是對tcp/ip協議棧操作的抽象,而不是簡單的對映關係,這很重要!

1、tcp連線

手機能夠使用聯網功能是因為手機底層實現了tcp/ip協議,可以使手機終端通過無線網路建立tcp連線。tcp協議可以對上層網路提供介面,使上層網路資料的傳輸建立在「無差別」的網路之上。

建立起乙個tcp連線需要經過「三次握手」:

第一次握手:客戶端傳送syn包(syn=j)到伺服器,並進入syn_send狀態,等待伺服器確認;

第二次握手:伺服器收到syn包,必須確認客戶的syn(ack=j+1),同時自己也傳送乙個syn包(syn=k),即syn+ack包,此時伺服器進入syn_recv狀態;

第三次握手:客戶端收到伺服器的syn+ack包,向伺服器傳送確認包ack(ack=k+1),此包傳送完畢,客戶端和伺服器進入established狀態,完成三次握手。

握手過程中傳送的包裡不包含資料,三次握手完畢後,客戶端與伺服器才正式開始傳送資料。理想狀態下,tcp連線一旦建立,在通訊雙方中的任何一方主動關閉連線之前,tcp 連線都將被一直保持下去。斷開連線時伺服器和客戶端均可以主動發起斷開tcp連線的請求,斷開過程需要經過「四次握手」(過程就不細寫了,就是伺服器和客戶端互動,最終確定斷開)

2、http連線

http協議即超文字傳送協議(hypertext transfer protocol ),是web聯網的基礎,也是手機聯網常用的協議之一,http協議是建立在tcp協議之上的一種應用。

http連線最顯著的特點是客戶端傳送的每次請求都需要伺服器回送響應,在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為「一次連線」。

1)在http 1.0中,客戶端的每次請求都要求建立一次單獨的連線,在處理完本次請求後,就自動釋放連線。

2)在http 1.1中則可以在一次連線中處理多個請求,並且多個請求可以重疊進行,不需要等待乙個請求結束後再傳送下乙個請求。

3、socket原理

3.1套接字(socket)概念

套接字(socket)是通訊的基石,是支援tcp/ip協議的網路通訊的基本操作單元。它是網路通訊過程中端點的抽象表示,包含進行網路通訊必須的五種資訊:連線使用的協議,本地主機的ip位址,本地程序的協議埠,遠地主機的ip位址,遠地程序的協議埠。

應用層通過傳輸層進行資料通訊時,tcp會遇到同時為多個應用程式程序提供併發服務的問題。多個tcp連線或多個應用程式程序可能需要通過同乙個 tcp協議埠傳輸資料。為了區別不同的應用程式程序和連線,許多計算機作業系統為應用程式與tcp/ip協議互動提供了套接字(socket)介面。應用層可以和傳輸層通過socket介面,區分來自不同應用程式程序或網路連線的通訊,實現資料傳輸的併發服務

TCP IP和Socket的關係

要寫網路程式就必須用socket,這是程式設計師都知道的。而且,面試的時候,我們也會問對方會不會socket程式設計?一般來說,很多人都會說,socket程式設計基本就是listen,accept以及send,write等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。對於網路程式...

TCP IP和Socket的關係

要寫網路程式就必須用socket,這是程式設計師都知道的。而且,面試的時候,我們也會問對方會不會socket程式設計?一般來說,很多人都會說,socket程式設計基本就是listen,accept以及send,write等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。對於網路程式...

TCP IP和Socket的關係

要寫網路程式就必須用socket,這是程式設計師都知道的。而且,面試的時候,我們也會問對方會不會socket程式設計?一般來說,很多人都會說,socket程式設計基本就是listen,accept以及send,write等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。對於網路程式...