写点什么

网络协议之:socket 协议详解之 Datagram Socket

作者:程序那些事
  • 2022 年 3 月 14 日
  • 本文字数:2608 字

    阅读完需:约 9 分钟

网络协议之: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 successfullyNcat: 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 successfullyNcat: 1 bytes sent, 0 bytes received in 2.02 seconds.
复制代码


表示 UDP 连接成功。

总结

本文讲解了 datagram socket 的基本概念,并且使用一些 unix 的基本命令来构建了 udp 服务器和客户端,方便大家理解。


本文已收录于 http://www.flydean.com/16-datagram-socket/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
网络协议之:socket协议详解之Datagram Socket_socket_程序那些事_InfoQ写作平台