golangtcp,golangtcp透明代理

本文目錄一覽:

【golang】高並發下TCP常見問題解決方案

首先,看一下TCP握手簡單描繪過程:

其握手過程原理,就不必說了,有很多詳細文章進行敘述,本文只關注研究重點。

在第三次握手過程中,如果伺服器收到ACK,就會與客戶端建立連接,此時內核會把連接從半連接隊列移除,然後創建新的連接,並將其添加到全連接隊列,等待進程調用。

如果伺服器繁忙,來不及調用連接導致全連接隊列溢出,伺服器就會放棄當前握手連接,發送RST給客戶端,即connection reset by peer。

在linux平台上,客戶端在進行高並發TCP連接處理時,最高並發數量都要受系統對用戶單一進程同時打開文件數量的限制(這是因為系統每個TCP都是SOCKET句柄,每個soker句柄都是一個文件),當打開連接超過限制,就會出現too many open files。

使用下指令查看最大句柄數量:

增加句柄解決方案

Golang 網路編程絲綢之路 – TCP/UDP 地址解析

TL;DR 在使用 Golang 編寫 TCP/UDP socket 的時候,第一步做的就是地址解析。

該函數返回的地址包含的信息如下:

TCPAddr 里, IP 既可以是 IPv4 地址,也可以是 IPv6 地址。 Port 就是埠了。 Zone 是 IPv6 本地地址所在的區域。

從返回結果看該函數的參數, network 指 address 的網路類型; address 指要解析的地址,會從中解析出我們想要的 IP , Port 和 Zone 。

從源碼中可以看出,參數 network 只能是如下四個值,否則會得到一個錯誤。

解析過程跟 ResolveTCPAddr 的一樣,不過得到的是 *UDPAddr 。

UDPAddr 包含的信息如下:

TCP那些事兒

目錄:

以前我也認為TCP是相當底層的東西,我永遠不需要去了解它。雖然差不多是這樣,但是實際生活中,你依然可能遇見和TCP演算法相關的bug,這時候懂一些TCP的知識就至關重要了。( 本文也可以引申為,系統調用,操作系統這些都很重要,這個道理適用於很多東西 )

這裡推薦一篇小短文, 人人都應該懂點TCP

使用TCP協議通信的雙方必須先建立TCP連接,並在內核中為該連接維持一些必要的數據結構,比如連接的狀態、讀寫緩衝區、定時器等。當通信結束時,雙方必須關閉連接以釋放這些內核數據。TCP服務基於流,源源不斷從一端流向另一端,發送端可以逐位元組寫入,接收端可以逐位元組讀出,無需分段。

需要注意的幾點:

TCP狀態(11種):

eg.

以上為TCP三次握手的狀態變遷

以下為TCP四次揮手的狀態變遷

伺服器通過 listen 系統調用進入 LISTEN 狀態,被動等待客戶端連接,也就是所謂的被動打開。一旦監聽到SYN(同步報文段)請求,就將該連接放入內核的等待隊列,並向客戶端發送帶SYN的ACK(確認報文段),此時該連接處於 SYN_RECVD 狀態。如果伺服器收到客戶端返回的ACK,則轉到 ESTABLISHED 狀態。這個狀態就是連接雙方能進行全雙工數據傳輸的狀態。

而當客戶端主動關閉連接時,伺服器收到FIN報文,通過返回ACK使連接進入 CLOSE_WAIT 狀態。此狀態表示——等待伺服器應用程序關閉連接。通常,伺服器檢測到客戶端關閉連接之後,也會立即給客戶端發送一個FIN來關閉連接,使連接轉移到 LAST_ACK 狀態,等待客戶端對最後一個FIN結束報文段的最後一次確認,一旦確認完成,連接就徹底關閉了。

客戶端通過 connect 系統調用主動與伺服器建立連接。此系統調用會首先給伺服器發一個SYN,使連接進入 SYN_SENT 狀態。

connect 調用可能因為兩種原因失敗:1. 目標埠不存在(未被任何進程監聽)護著該埠被 TIME_WAIT 狀態的連接佔用( 詳見後文 )。2. 連接超時,在超時時間內未收到伺服器的ACK。

如果 connect 調用失敗,則連接返回初始的 CLOSED 狀態,如果調用成功,則轉到 ESTABLISHED 狀態。

客戶端執行主動關閉時,它會向伺服器發送一個FIN,連接進入 TIME_WAIT_1 狀態,如果收到伺服器的ACK,進入 TIME_WAIT_2 狀態。此時伺服器處於 CLOSE_WAIT 狀態,這一對狀態是可能發生辦關閉的狀態(詳見後文)。此時如果伺服器發送FIN關閉連接,則客戶端會發送ACK進行確認並進入 TIME_WAIT 狀態。

流量控制是為了控制發送方發送速率,保證接收方來得及接收。

接收方發送的確認報文中的窗口欄位可以用來控制發送方窗口大小,從而影響發送方的發送速率。將窗口欄位設置為 0,則發送方不能發送數據。

如果網路出現擁塞,分組將會丟失,此時發送方會繼續重傳,從而導致網路擁塞程度更高。因此當出現擁塞時,應當控制發送方的速率。這一點和流量控制很像,但是出發點不同。 流量控制是為了讓接收方能來得及接收,而擁塞控制是為了降低整個網路的擁塞程度。

TCP 主要通過四種演算法來進行擁塞控制: 慢開始、擁塞避免、快重傳、快恢復。

在Linux下有多種實現,比如reno演算法,vegas演算法和cubic演算法等。

發送方需要維護一個叫做擁塞窗口(cwnd)的狀態變數,注意擁塞窗口與發送方窗口的區別:擁塞窗口只是一個狀態變數,實際決定發送方能發送多少數據的是發送方窗口。

為了便於討論,做如下假設:

發送的最初執行慢開始,令 cwnd=1,發送方只能發送 1 個報文段;當收到確認後,將 cwnd 加倍,因此之後發送方能夠發送的報文段數量為:2、4、8 …

注意到慢開始每個輪次都將 cwnd 加倍,這樣會讓 cwnd 增長速度非常快,從而使得發送方發送的速度增長速度過快,網路擁塞的可能也就更高。設置一個慢開始門限 ssthresh,當 cwnd = ssthresh 時,進入擁塞避免,每個輪次只將 cwnd 加 1。

如果出現了超時,則令 ssthresh = cwnd/2,然後重新執行慢開始。

在接收方,要求每次接收到報文段都應該對最後一個已收到的有序報文段進行確認。例如已經接收到 M1 和 M2,此時收到 M4,應當發送對 M2 的確認。

在發送方,如果收到三個重複確認,那麼可以知道下一個報文段丟失,此時執行快重傳,立即重傳下一個報文段。例如收到三個 M2,則 M3 丟失,立即重傳 M3。

在這種情況下,只是丟失個別報文段,而不是網路擁塞。因此執行快恢復,令 ssthresh = cwnd/2 ,cwnd = ssthresh,注意到此時直接進入擁塞避免。

慢開始和快恢復的快慢指的是 cwnd 的設定值,而不是 cwnd 的增長速率。慢開始 cwnd 設定為 1,而快恢復 cwnd 設定為 ssthresh。

  發送端的每個TCP報文都必須得到接收方的應答,才算傳輸成功。

  TCP為每個TCP報文段都維護一個重傳定時器。

  發送端在發出一個TCP報文段之後就啟動定時器,如果在定時時間類未收到應答,它就將重發該報文段並重置定時器。

  因為TCP報文段最終在網路層是以IP數據報的形式發送,而IP數據報到達接收端可能是亂序或者重複的。TCP協議會對收到的TCP報文進行重排、整理,確保順序正確。

TCP報文段所攜帶的應用程序數據按照長度分為兩種: 交互數據 和 成塊數據

對於什麼是粘包、拆包問題,我想先舉兩個簡單的應用場景:

對於第一種情況,服務端的處理流程可以是這樣的:當客戶端與服務端的連接建立成功之後,服務端不斷讀取客戶端發送過來的數據,當客戶端與服務端連接斷開之後,服務端知道已經讀完了一條消息,然後進行解碼和後續處理…。對於第二種情況,如果按照上面相同的處理邏輯來處理,那就有問題了,我們來看看 第二種情況 下客戶端發送的兩條消息遞交到服務端有可能出現的情況:

第一種情況:

服務端一共讀到兩個數據包,第一個包包含客戶端發出的第一條消息的完整信息,第二個包包含客戶端發出的第二條消息,那這種情況比較好處理,伺服器只需要簡單的從網路緩衝區去讀就好了,第一次讀到第一條消息的完整信息,消費完再從網路緩衝區將第二條完整消息讀出來消費。

第二種情況:

服務端一共就讀到一個數據包,這個數據包包含客戶端發出的兩條消息的完整信息,這個時候基於之前邏輯實現的服務端就蒙了,因為服務端不知道第一條消息從哪兒結束和第二條消息從哪兒開始,這種情況其實是發生了TCP粘包。

第三種情況:

服務端一共收到了兩個數據包,第一個數據包只包含了第一條消息的一部分,第一條消息的後半部分和第二條消息都在第二個數據包中,或者是第一個數據包包含了第一條消息的完整信息和第二條消息的一部分信息,第二個數據包包含了第二條消息的剩下部分,這種情況其實是發送了TCP拆,因為發生了一條消息被拆分在兩個包裡面發送了,同樣上面的伺服器邏輯對於這種情況是不好處理的。

我們知道tcp是以流動的方式傳輸數據,傳輸的最小單位為一個報文段(segment)。tcp Header中有個Options標識位,常見的標識為mss(Maximum Segment Size)指的是,連接層每次傳輸的數據有個最大限制MTU(Maximum Transmission Unit),一般是1500比特,超過這個量要分成多個報文段,mss則是這個最大限制減去TCP的header,光是要傳輸的數據的大小,一般為1460比特。換算成位元組,也就是180多位元組。

tcp為提高性能,發送端會將需要發送的數據發送到緩衝區,等待緩衝區滿了之後,再將緩衝中的數據發送到接收方。同理,接收方也有緩衝區這樣的機制,來接收數據。

發生TCP粘包、拆包主要是由於下面一些原因:

既然知道了tcp是無界的數據流,且協議本身無法避免粘包,拆包的發生,那我們只能在應用層數據協議上,加以控制。通常在制定傳輸數據時,可以使用如下方法:

寫了一個簡單的 golang 版的tcp伺服器實例,僅供參考:

例子

參考和推薦閱讀書目:

注釋:

eg.

原創文章,作者:EVMF,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/131439.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
EVMF的頭像EVMF
上一篇 2024-10-03 23:45
下一篇 2024-10-03 23:45

相關推薦

  • 中國地圖png透明素材的全面解析

    一、透明背景的定義和作用 中國地圖png透明素材一般是指背景透明的中國地圖圖像文件,請注意,這裡不同於沒有背景的中國地圖,背景透明是指圖像的背景色為完全透明,可以和其他圖片或背景融…

    編程 2025-02-15
  • 詳解el-table背景透明

    一、背景 在實際項目中,常常需要進行表格數據的展示。而el-table是ElementUI提供的一個常用的表格組件。其中,el-table的樣式分為兩部分,一部分是表格主體樣式,另…

    編程 2025-02-11
  • CSS 透明色詳解

    一、透明色的概念 透明是一種屬性,指的是物體可以透過,這在css中的表示就是opacity屬性,值可以在0(完全透明)和1(完全不透明)之間,這裡我們主要介紹的是背景透明,即bac…

    編程 2025-02-01
  • c語言pnl,c語言png透明

    本文目錄一覽: 1、電腦系統基礎知識書籍 2、求高人給我發幾個關於C51單片機PWM的編程實例 3、電腦主板基礎實用知識 4、在學delphi的中途再加java會不會太難 5、單片…

    編程 2025-01-14
  • 使用imagecolorallocatealpha創建PHP圖像透明顏色

    在PHP中,我們可以使用GD庫來創建圖像。而使用imagecolorallocatealpha函數,我們可以為圖像創建透明顏色。 一、imagecolorallocatealpha…

    編程 2024-12-24
  • 全面了解RGBA透明色

    一、RGB值是多少 RGB顏色模型是指通過對紅、綠、藍三個顏色通道的變化以不同的比例來得到各式各樣的顏色,它能夠表示出256*256*256=16777216種顏色,其中最常用的透…

    編程 2024-12-24
  • 3dmax貼圖做透明亞克力,3dmax半透明貼圖

    本文目錄一覽: 1、3Ds Max如何做透明貼圖? 2、3dmax透明貼圖怎麼弄 3、3dmax透明亞克力材質參數是什麼,怎麼調? 4、3Dmax中,透明的亞克力材質怎麼調? 5、…

    編程 2024-12-14
  • Android活動實現全屏透明效果

    一、概述 在開發Android應用的過程中,有時需要實現全屏的透明效果,讓應用從而更加美觀和吸引人。全屏透明效果可以在應用啟動時或者在特定頁面啟動時使用,既可以讓應用獨具特色,又能…

    編程 2024-12-12
  • 白色透明背景色的應用實例

    一、透明度的概念 在CSS中,我們可以使用opacity屬性來設置元素的透明度,它的取值範圍是0~1,其中0表示完全透明,1表示完全不透明。透明度不僅可以應用在顏色上,還可以應用在…

    編程 2024-12-12
  • 讓文本漸變透明:CSS中的漸變效果

    一、什麼是漸變效果? 在CSS中,漸變效果是指將一個顏色逐漸轉變為另一種顏色的效果。CSS中可以實現線性漸變、徑向漸變和角向漸變。漸變效果可以應用於文本、背景、邊框等多個元素上。 …

    編程 2024-12-12

發表回復

登錄後才能評論