天天看點

C#網絡程式設計入門之TCP

UDP和TCP是網絡通訊常用的兩個傳輸協定,C#一般可以通過Socket來實作UDP和TCP通訊,由于.NET架構通過UdpClient、TcpListener 、TcpClient這幾個類對Socket進行了封裝,使其使用更加友善, 本文就通過這幾個封裝過的類講解一下相關應用。

UDP和TCP是網絡通訊常用的兩個傳輸協定,C#一般可以通過Socket來實作UDP和TCP通訊,由于.NET架構通過UdpClient、TcpListener 、TcpClient這幾個類對Socket進行了封裝,使其使用更加友善, 本文就通過這幾個封裝過的類講解一下相關應用。

服務端建立偵聽并等待連接配接:

服務端是通過AcceptTcpClient方法獲得TcpClient對象,而用戶端是直接建立TcpClient對象。

發送資料TcpClient對象建立後,發送接收都通過TcpClient對象完成。

發送資料:

接收資料:

和UDP不太一樣,TCP連接配接不會丢包,但存在粘包問題。(嚴格來說粘包這個說法是不嚴謹的,因為TCP通訊是基于流的,沒有包的概念,包隻是使用者自己的了解。) 下面分析一下粘包産生的原因及解決辦法。

TCP資料通訊是基于流來實作的,類似一個隊列,當有資料發送過來時,作業系統就會把發送過來的資料依次放到這個隊列中,對發送者而言,資料是一片一片發送的,是以自然會認為存在資料包的概念,但對于接收者而言,如果沒有及時去取這些資料,這些資料依次存放在隊列中,彼此之間并無明顯間隔,自然就粘包了。

還有一種情況粘包是發送端造成的,有時我們調用發送代碼時,作業系統可能并不會立即發送,而是放到緩存區,當緩存區達到一定數量時才真正發送。 

要解決粘包問題,大緻有以下幾個方案。

1、 約定資料長度,發送端的資料都是指定長度,比如1024;接收端取資料時也取同樣長度,不夠長度就等待,保證取到的資料和發送端一緻;

2、 接收端取資料的頻率遠大于發送端,比如發送端每1秒發送一段資料,接收端每0.1秒去取一次資料,這樣基本可以保證資料不會粘起來;

以上兩個方案都要求發送端需要立即發送,不可緩存資料。而且這兩種方案都有缺陷:首先,第一種方案:如果要包大小一緻的話,如果約定的包比較大,肯定有較多資料備援,浪費網絡資源,如果包較小,連接配接就比較頻繁,效率不高。

其次,第二種方案:這個方案隻能在理想環境下可以實作,當服務端遭遇一段時間的計算壓力時可能會出現意外,不能完全保證。

比較完善的解決方案就是對接收到的資料進行預處理:首先通過定義特殊的字元組合作為標頭和包尾,如果傳輸ASCII字元,可以用0x02表示開始(STX),用0x03表示結束(ETX),比如:STX ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ETX (二進制資料: 02 48 65 6C 6C 6F 03)。如果資料較長可以在標頭留出固定位置存放包長度, 如:

02 00 05 48 65 6C 6C 6F 03

其中02 05 就表示正文長度為5個位元組,可以進行校驗。

雖然第三種方案比較嚴謹,但相對複雜,在傳輸比較可靠、應用比較簡單的場景下,也可以采用前面兩種解決方案。

 服務端:

C#網絡程式設計入門之TCP
C#網絡程式設計入門之TCP

View Code

用戶端:

C#網絡程式設計入門之TCP
C#網絡程式設計入門之TCP

C#網絡程式設計入門系列包括三篇文章:

(一)C#網絡程式設計入門之UDP

(二)C#網絡程式設計入門之TCP

(三)C#網絡程式設計入門之HTTP

簽名區:

如果您覺得這篇部落格對您有幫助或啟發,請點選右側【推薦】支援,謝謝!

繼續閱讀