TCP IP和Socket開發經驗分享

2022-02-01 06:08:20 字數 1495 閱讀 5784

比較常見的4層網路模型(圖)如下:

基於應用層的開發難度是相對比較低的,因為絕大部分與連線和資料傳輸、校驗相關的事情已經交給(系統)來完成,使得開發人員只需要專注於業務即可。這種分層的技術結構是非常高階和有效的。基於應用層的開發雖然方便,但是當我們需要在功能上實現某些特殊需求的時候,就難免有些掣肘。例如,我們需要從一些感測器上採集資料或希望他們能夠主動將資料上送,並在經過了中心系統處理後推送到其它響應裝置。這樣的需求使用http來開發,反而增大了難度。

作業系統實際已經為我們提供了一種基於傳輸層的通訊方式:套接字(socket)。使用套接字可以讓我們自由定義通訊協議並選擇合適的連線方式。

利用socket實現網路通訊分為服務端和客戶端,服務端繫結埠並主動監聽連線,客戶端需要向服務端發起連線。建立一次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狀態,完成三次握手。

三次握手被抽象成socket連線,這個過程服務端和客戶端會分別生成乙個socket並通過在這個套接字上的連線收發資料。那麼問題產生了,假如我們知道服務端對8081埠進行監聽,客戶端會隨機開啟乙個高位埠進行連線。連線建立後,服務端是在哪個埠上監聽資料的呢?答案是8081埠,服務端會根據埠上資料的源位址和埠判斷從而將資料分發到正確的應用上去。

理解這一點其實很重要,如果此時通訊的雙方沒有任何資料交換,socket也無法判斷連線是否被斷開。任意一方必須首先通知socket斷開連線,整個通訊過程才算結束。如果中間網路中斷,連線會一直處於等待狀態。

利用socket程式設計的另乙個難點是,由於通訊的雙方完全對等任何一方都可以主動傳送資料,如何實現在http應用中常見的請求/應答會比較麻煩。為此我專門查閱了http1.0和http1.1的相關資料,基本的解決方案總結如下:

客戶端等待:客戶端傳送請求後,都需要進行堵塞並直到接收到應答或超時為止。這個是http1.0的協議規範,整個資料的互動方式是序列的。

伺服器的運算能力通常都比客戶端強,第二種解決方案能更加有效的利用網路。但是,如果有一條請求需要請求占用服務端大量的運算時間,後續應答都會被堵塞,因此在某些情況下也會引發比較嚴重的問題。

為了解決這個問題,我借鑑了spring kafka在實現訊息互動的時候提供的一種解決思路:為每一條請求指定乙個id,經過服務端處理後的應答都需要帶上這個id。這樣在回覆給客戶端的時候,客戶端就可以根據這條id值來呼叫不同的**處理業務。

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等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。對於網路程式...