網絡協議之:socket協議詳解之Datagram Socket


簡介

上一篇文章我們講解了Socket的分類和最常用到的Stream Socket,Stream Socket一般是基於TCP協議的,所以我們經常在web服務中能夠看到他們的身影。當然TCP協議有個孿生兄弟叫做UDP,那么基於UDP來做傳輸協議的socket協議就叫做Datagram Socket,今天我們一起來詳細了解一下Datagram Socket。

什么是Datagram Socket

和有連接的Stream Socket不同,Datagram Socket是無連接的。有連接的Stream Socket表明這個socket是穩定可靠的,所以我們可以在Stream socket中進行穩定的數據傳輸,當然這個穩定是說數據包不會丟失,但是並不一定能夠確保數據包不被篡改。

Datagram Socket這種無連接的通常被用在容許數據部分丟失的場景,比如語音、視頻等等,無連接的好處就是不需要TCP那樣復雜的建立連接的步驟,所以相對而言更加簡單。

Datagram Socket通常使用的就是UDP協議作為底層的數據傳輸協議。

對於UDP來說,因為UDP協議本身並不會保證數據的順序和數據異常的處理,這些都需要在應用程序中自己實現。

常見的UDP應用有DNS(Domain Name System)服務,NTP(Network Time Protocol)服務等等。

在JDK的java.net包中提供了對Datagram Socket的封裝,在其中定義了三個連接的狀態:

class DatagramSocket implements java.io.Closeable {
    ...
    static final int ST_NOT_CONNECTED = 0;
    static final int ST_CONNECTED = 1;
    static final int ST_CONNECTED_NO_IMPL = 2;
    ...
}

分別表示沒有建立連接,建立了連接和建立了連接,但是還沒有到實現的level。

另外,在DatagramSocket中還包含了一個連接的地址和端口:

InetAddress connectedAddress = null;
int connectedPort = -1;

使用socat來創建UDP服務

注意,在使用后續的命令之前,需要在unix環境中執行安裝命令:yum install iproute2 netcat-openbsd socat

和之前的Stream Socket一樣,我們也可以使用socat命令,來建立一個UDP服務器,我們需要用到socat的下面幾個參數:

      udp4-listen:<port>        groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP4,UDP
      udp6-listen:<port>        groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP6,UDP

我們需要監聽udp4和udp6的數據,所以這里使用 udp4-listen和udp6-listen兩個參數。

后面的端口號可以自定義,這里我們還是使用同樣的8888端口,對應的命令如下:

socat UDP4-LISTEN:8888,fork /dev/null&
socat UDP6-LISTEN:8888,ipv6only=1,fork /dev/null&

上面的命令,我們在8888端口上監聽UDP4和UDP6的連接信息,其中fork參數表示程序在接收到程序包之后繼續運行,如果不用fork,那么程序會自動退出。

socat后面本來要接一個bi-address,這里我們使用/dev/null,表示丟棄掉所有的income信息。

UDP6-LISTEN有個特殊的參數叫做ipv6only,表示收到的數據包不要發送到IPv4-mapped IPv6 addresses。

什么是IPv4-mapped IPv6 addresses? 簡單點說就是將IPv4映射到了IPv6的地址中。

執行上述命令,我們會得到下面的輸出:

[1] 16174
[2] 16184

因為是后台執行,所以我們返回了進程的ID。

使用ss命令來監控Datagram Sockets

ss命令可以用來檢查socket的狀態,這里我們需要用到ss的這樣幾個參數:

   -4, --ipv4          display only IP version 4 sockets
   -u, --udp           display only UDP sockets
   -l, --listening     display listening sockets
   -n, --numeric       don't resolve service names

因為我們只監聽ipv4和ipv6的數據,所以這里我們用-4和-6這兩個參數。

另外因為只需要監聽udp sockets,所以需要使用-u參數。

因為是監聽,所以使用-l參數,最后我們希望看到具體的數字,而不是被解析成了服務名,所以這里使用-n參數。

我們使用下面的命令看看結果:

ss -4 -uln

可以得到下面的結果:

State       Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
UNCONN      0      0                                       *:8888                                                *:*  

上面的命令只監聽了Ipv4,我們再看看Ipv6:

ss -6 -uln

可以得到下面的結果:

State       Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
UNCONN      0      0                                      :::8888                                               :::*  

和Ipv4的很類似,表示我們在Ipv6上監聽到了端口8888。

使用nc建立和UDP Socket的連接

我們已經建立好了了監聽UDP連接的服務器,接下來我們嘗試使用nc命令來進行連接。

nc是Ncat的簡稱,是一個非常小並且高效的網絡工具。我們來看下本例子中會用到的參數:

  -4                         Use IPv4 only
  -6                         Use IPv6 only
  -u, --udp                  Use UDP instead of default TCP
  -v, --verbose              Set verbosity level (can be used several times)
  -z                         Zero-I/O mode, report connection status only

因為需要連接到Ipv4和Ipv6,所以需要-4和-6參數。

默認情況下nc使用的是TCP協議,如果要使用udp則需要使用-u這個參數。

另外我們需要輸出詳細的信息,所以需要-v參數,最后我們直接建立連接,並不發送任何數據,所以這里使用-z參數,我們執行一下來看看效果:

nc -4 -u -vz 127.0.0.1 8888

看看下面的輸出結果:

Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:8888.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.02 seconds.

表示UDP連接成功。

同樣的,我們可以使用下面的命令來連接到UDP socket:

nc -6 -u -vz ::1 8888

其中::1表示的是本機的ipv6地址.

可以得到下面的結果:

Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to ::1:8888.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.02 seconds.

表示UDP連接成功。

總結

本文講解了datagram socket的基本概念,並且使用一些unix的基本命令來構建了udp服務器和客戶端,方便大家理解。

本文已收錄於 http://www.flydean.com/16-datagram-socket/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM