前言
簡單的說,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 更快呢?
-
收發資料前後進行的連線設定及清除過程。也就是連線和斷開。
-
收發資料過程中為保證可靠性而新增的流控制。
那麼是不是我們需要更快的傳輸就使用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的關閉。