計算機網路再次整理————UDP例子[六]

敖毛毛發表於2022-02-06

前言

簡單的說,UDP 沒有 TCP 用的廣泛,但是還有很多是基於UDP的程式的,故而簡單介紹一下。

正文

秉承節約腦容量的問題,只做簡單的介紹和例子,因為自己幾乎也沒怎麼用過UDP。

只是瞭解和知曉其中的用途,那麼設計方案的時候有特定的場景,那麼可以參考。

UDP 和 TCP 最大的不同的地方是傳輸方式,不然他們也不會在傳輸層進行分叉。

UDP 不知道對方是否存在,那麼會直接傳送資訊出去,對方也不會告訴你是否收到了,是否需要重傳。

有些人把TCP 比作是接打電話,那麼UDP就像是投遞郵件了。

UDP 只要將對方的地址和寫信的內容進行投遞,那麼網路基礎設施就會幫我們把信件投遞出去。

那麼即使信件中途丟失,我們也是不知道的。我們能知道的是,我們的信是否交到了郵件員手中。

還有和TCP 一個最大的區別,我們收郵件的時候只需要放置一個郵箱。而我們同時接打電話的時候,需要多臺電話機。

是的,如果是UDP 那麼服務端只需要建立一個socket的。如果是TCP,那麼一個客戶端,服務端就要多建立一個socket了。

我們說UDP 是無序的、不可靠的、有資料邊界的。

有資料邊界的是因為UDP 不是流的,每對作業系統的UDP傳送資訊介面呼叫一次,那麼就會發出去一次,也就是會進行一次網路io。

無序的,這個比較好理解,因為網路中路由的選擇啊,演算法啊,等等因素,那麼可能傳送1、2、3,收到的是3、1、2,或者其他組合。

那麼說其是不可靠的,這個也比較好理解了,因為不像UDP那麼複雜,沒有那麼多保障措施。

說起來UDP更加簡單了,我們知道簡單的東西在計算機上,基本意味這更快。

為什麼UDP 更快呢?

  1. 收發資料前後進行的連線設定及清除過程。也就是連線和斷開。

  2. 收發資料過程中為保證可靠性而新增的流控制。

那麼是不是我們需要更快的傳輸就使用udp呢?這不是的,首先我們一定是首選tcp的,當tcp不滿足我們的時候那麼才使用udp。

也不要認為udp跟快,那麼就使用udp能提高效能。

tcp和udp的速度差距不是我們想象的那麼快,而tcp帶來了可靠。如果是在傳輸資料量大的時候,我們的tcp和udp的速度是很接近的。

一般在傳輸視訊的時候可以使用udp,因為即使有某段丟包,那麼也就是卡幀的問題。

因為udp包裡面的資料可以帶時間,那麼其順序就沒有那麼重要,應用程式可以處理。

udp的場景,那麼適合不在意包的順序,同時對丟包沒有那麼敏感。當然udp也可以在應用層協議中有重傳等保證資料的機制,但是這樣為啥不直接使用tcp呢。

實驗程式碼:
service:

// See https://aka.ms/new-console-template for more information

using System.Net;
using System.Net.Sockets;

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Bind(endPoint);
while (true)
{
    Console.WriteLine("開始接收");
    var receiveMessage = new Byte[1000];
    socket.Receive(receiveMessage);
    Console.WriteLine(System.Text.Encoding.UTF8.GetString(receiveMessage));
    Console.WriteLine("接收完畢");
}

client:


using System.Net;
using System.Net.Sockets;

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Connect(endPoint);
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service"));
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service2"));
Console.WriteLine("傳送成功");
// 收到的包
var receive = new byte[1000];
socket.ReceiveFrom(receive,SocketFlags.OutOfBand, ref  endPoint);
Console.WriteLine(receive);
Console.ReadLine();

可以看到在客戶端這裡,我寫了一個ReceiveFrom。

那麼我做了一個這樣的實驗,就是我不啟動服務端然後開啟客戶端的情況下,我使用了ReceiveFrom。

那麼會丟擲異常,那麼這個異常是如何丟擲來的呢?或者說是不是有一個試探包傳送,看是否有回應呢。

這個異常丟擲是因為收到了icmp包,也就是埠不可達。假如我們直接ReceiveFrom,那麼是不會傳送異常的,那麼我們程式做的事情就是呼叫作業系統的api,詢問是否有新的訊息,作業系統沒有給,那麼其實處於一個阻塞狀態。

這裡想說明的一點就是udp和tcp這種傳輸層,不要和ip層弄混,ip層有的協議,udp和tcp都有。

抓包截圖:

下一結介紹一些tcp的關閉。

相關文章