写点什么

网络协议之:socket 协议详解之 Socket 和 Stream Socket

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

    阅读完需:约 11 分钟

网络协议之:socket协议详解之Socket和Stream Socket

简介

不管是在普通的网络编程中还是在 netty 中,都经常会提到一个词叫做 socket,好像 socket 是一个神奇的东西,使用 socket 我们可以建立客户端到服务器端的连接,并且和进行客户端和服务器端的通讯,那么 socket 到底是什么呢?它有哪些分类呢?一起来看看吧。

Socket 是什么

socket 的中文翻译是套接字,个人觉的这个翻译真的是太差劲了,套接字听起来毫无意义,所以很多人在第一次听到 socket 这个词的时候肯定很迷茫。


那么什么是 socket 呢?socket 是一种不同程序间进行进程通讯的方法,这些程序可以在同一个服务器上也可以在不同的服务器上。


socket 建立连接的基础是 IP 协议,IP 协议被用来进行数据的封装和分组,然后才能够在网络上进行传输。这种依赖于 IP 协议的 socket,又叫做 network socket。


通过 network socket 可以建立客户端和服务器端的连接,客户端和服务器端是通过 socket address 来发现对方的。


以 java 为例,我们来看下 SocketAddress 的定义:


public abstract class SocketAddress implements java.io.Serializable {
static final long serialVersionUID = 5215720748342549866L;
}
复制代码


可以看到 SocketAddress 只是一个笼统的定义,它可以有多种实现,它具体的实现中包含了传输协议,比如说是 TCP,还是 UDP,另外还需要包含一个 IP 地址和一个连接的端口。


其中 IP 地址和端口定义了连接的对象,协议定义的是连接方式。


基于不同的协议,可以衍生出不同的类型的 sockets。比如依赖于 TCP 协议的叫做 Stream sockets,依赖于 UDP 协议的叫做 Datagram sockets,依赖于 local files 来进行数据传输的叫做 Unix Domain Sockets.


接下来我们会在一个 unix 系统中详细讲解这几种协议的使用。


在讲解详细的例子之前,我们需要使用到关于网络的命令,他们是 ss,nc 和 socat。


在本文中,我使用的是 centOS 系统,所以你可以使用下面的命令进行安装:


yum install iproute2 netcat-openbsd socat
复制代码

Stream Socket

什么是 Stream Socket 呢?从字面上可以看出,这个 Socket 连接是用来进行流传输的,如果要进行流的传输,那么首先就需要建立一个稳定的网络连接,在稳定的连接方面,毫无疑问 TCP(Transmission Control Protocol)是最常用也是极其高效的一种协议。


对于 Stream Socket 来说,它是有向性的,数据 package 需要从一个地址通过网络传递到另外一个地址,同时还需要接受到对方的处理返回结果,在这个过程中通常使用的就是 TCP 协议。


TCP 协议能够保证数据的稳定性和有序性,TCP 的数据包可以保证发送到物理网络接口的数据包顺序。 如果网络接口接收到的数据包是无序的,那么网络适配器和操作系统将确保它们以正确的顺序重新组合以供应用程序使用。


常见的基于 TCP 的 Stream Socket 就是我们常常访问的 http 和 https 服务了,处理 http 和 https 服务的服务器一般是 nginx 或者 apache,那么通常会有下面的 Stream Socket 地址:


124.225.141.53:80124.225.141.53:443
复制代码


上面我用的是网易的 ip 地址,其中 80 表示的是 http,443 表示的是 https。

使用 socat 创建一个 TCP 服务器

常用的 TCP 服务器可以选择 apache 或者 nginx,这里为了简单起见,我们选择使用 socat 来创建一个 TCP 服务器。


socat 是什么呢?它是 SOcket CAT 的简称,可以用来模拟一个 TCP 的服务器。


socat 的命令很复杂,这里我们只是简单介绍一下它的应用:


socat -hsocat by Gerhard Rieger and contributors - see www.dest-unreach.orgUsage:socat [options] <bi-address> <bi-address>
复制代码


从上面的结果我们可以看出,socat 可以接受一些地址,然后可以添加一些选项。


这里我们使用 socat 来创建两个连接,分别是 TCP6 和 TCP4,socat 有两个选项可以做这项工作:


      tcp-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP      tcp-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCP      tcp4-connect:<host>:<port>        groups=FD,SOCKET,CHILD,RETRY,IP4,TCP      tcp4-listen:<port>        groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,TCP      tcp6-connect:<host>:<port>        groups=FD,SOCKET,CHILD,RETRY,IP6,TCP      tcp6-listen:<port>        groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,TCP
复制代码


这里我们只需要建立两个监听 TCP 的服务,所以我们使用下面的命令:


socat TCP4-LISTEN:8888,fork /dev/null&socat TCP6-LISTEN:8888,ipv6only=1,fork /dev/null&
复制代码


上面的命令,我们在 8888 端口上监听 TCP4 和 TCP6 的连接信息,其中 fork 参数表示程序在接收到程序包之后继续运行,如果不用 fork,那么程序会自动退出。


socat 后面本来要接一个 bi-address,这里我们使用/dev/null,表示丢弃掉所有的 income 信息。


TCP6-LISTEN 有个特殊的参数叫做 ipv6only,表示收到的数据包不要发送到 IPv4-mapped IPv6 addresses。


什么是 IPv4-mapped IPv6 addresses? 简单点说就是将 IPv4 映射到了 IPv6 的地址中。


执行上述命令,我们会得到下面的输出:


[1] 30877[2] 30885
复制代码


因为是后台执行,所以我们返回了进程的 ID。

使用 ss 检查 TCP 连接

ss 是一个非常强大的命令,我们可以通过使用 ss 来监测 TCP sockets 的信息,它的使用情况如下:


ss -hUsage: ss [ OPTIONS ]       ss [ OPTIONS ] [ FILTER ]
复制代码


我们主要看下面几个将要用到的参数:


   -4, --ipv4          display only IP version 4 sockets   -6, --ipv6          display only IP version 6 sockets   -t, --tcp           display only TCP sockets   -l, --listening     display listening sockets  -n, --numeric       don't resolve service names
复制代码


因为我们只监听 ipv4 和 ipv6 的数据,所以这里我们用-4 和-6 这两个参数。


另外因为只需要监听 tcp sockets,所以需要使用-t 参数。


因为是监听,所以使用-l 参数,最后我们希望看到具体的数字,而不是被解析成了服务名,所以这里使用-n 参数。


我们使用下面的命令看看结果:


ss -4 -tln
复制代码


结果如下:


State       Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
LISTEN 0 5 *:8888 *:*
复制代码


表示监听到了端口 8888, 当然如果你的服务器上有其他的进程,那么可能不止这一条数据。


上面的命令只监听了 Ipv4,我们再看看 Ipv6:


ss -6 -tln
复制代码


可能得到下面的输出:


ss -6 -tlnState       Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
LISTEN 0 5 :::8888 :::*
复制代码


和 Ipv4 的很类似,表示我们在 Ipv6 上监听到了端口 8888。

使用 nc 连接 socket

我们已经建立好了了监听 TCP 连接的服务器,接下来我们尝试使用 nc 命令来进行连接。


nc 是 Ncat 的简称,它是一个非常有用的网络工具,可以做很多事情。我们来看下本例子中会用到的参数:


  -4                         Use IPv4 only  -6                         Use IPv6 only  -v, --verbose              Set verbosity level (can be used several times)  -z                         Zero-I/O mode, report connection status only
复制代码


因为需要连接到 Ipv4 和 Ipv6,所以需要-4 和-6 参数。


另外我们需要输出详细的信息,所以需要-v 参数,最后我们直接建立连接,并不发送任何数据,所以这里使用-z 参数,我们执行一下来看看效果:


nc -4 -vz 127.0.0.1 8888
复制代码


看看下面的输出结果:


nc -4 -vz 127.0.0.1 8888Ncat: Version 7.50 ( https://nmap.org/ncat )Ncat: Connected to 127.0.0.1:8888.Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.
复制代码


可以看到 nc 已经成功建立了连接,并且发送了 0 bytes 的内容。


同样的,我们建立到 Ipv6 的连接:


nc -6 -vz ::1 8888
复制代码


这里的 ::1 表示的是 Ipv6 的本地地址。输出结果如下:


Ncat: Version 7.50 ( https://nmap.org/ncat )Ncat: Connected to ::1:8888.Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.
复制代码

总结

到此,我们介绍了 Socket 的基本分类 Stream Socket 的含义,并且使用 unix 中的工具搭建了 socket 服务器和客户端,当然这只是最简单的说明描述,大家用来体会 Stream Socket 的流程即可。


本文已收录于 http://www.flydean.com/15-stream-socket/

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

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

发布于: 刚刚阅读数: 2
用户头像

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

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

评论

发布
暂无评论
网络协议之:socket协议详解之Socket和Stream Socket_网络协议_程序那些事_InfoQ写作平台