電腦網路再次整理————UDP例子[六]
前言
簡單的說,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 //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的關閉。
