当前位置: 首页 > 后端技术 > Java

网络协议:Socket和SocketStream的socket协议详解

时间:2023-04-02 01:37:15 Java

介绍无论是在普通的网络编程中,还是在netty中,都会经常提到一个词叫socket,仿佛socket是一个神奇的东西。使用socket我们可以建立客户端到服务端的连接,实现客户端和服务端的通信,那么socket到底是什么?它有哪些类别?一起来看看吧。什么是套接字?socket的中文翻译是套接字。我个人认为这个翻译真的很糟糕。socket听起来没什么意思,所以很多人第一次听到socket这个词肯定是一头雾水。.那么什么是套接字?Socket是不同程序之间进行进程通信的一种方法,这些程序可以在同一个服务器上,也可以在不同的服务器上。建立套接字连接的基础是IP协议,用于对数据进行封装和分组,然后才能在网络上传输。这种依赖IP协议的套接字也称为网络套接字。客户端和服务器之间可以通过网络套接字建立连接,客户端和服务器通过套接字地址相互发现。以java为例,我们看一下SocketAddress的定义:publicabstractclassSocketAddressimplementsjava.io.Serializable{staticfinallongserialVersionUID=5215720748342549866L;}可以看到SocketAddress只是一个通用的定义,可以有多种实现.具体实现包括传输协议,如TCP或UDP,还需要包括IP地址和连接端口。其中,IP地址和端口定义了连接的对象,协议定义了连接方式。基于不同的协议,可以衍生出不同类型的套接字。例如,依赖于TCP协议的称为Streamsockets,依赖于UDP协议的称为Datagramsockets,依赖于本地文件进行数据传输的称为UnixDomainSockets。接下来,我们将在一个Unix系统中详细解释这些协议的使用。在讲解详细的例子之前,我们需要用到关于网络的命令,它们是ss、nc和socat。本文中我使用的是centOS系统,所以可以使用如下命令安装:yuminstalliproute2netcat-openbsdsocatStreamSocket什么是StreamSocket?从字面上可以看出,这个Socket连接是用来进行流传输的。如果要进行流式传输,首先需要建立稳定的网络连接。在稳定连接方面,毫无疑问,TCP(传输控制协议)是最常用且效率极高的协议。对于StreamSocket,是有方向的。数据包需要通过网络从一个地址传输到另一个地址,同时需要接收对方返回的处理结果。这个过程通常使用TCP协议。TCP协议可以保证数据的稳定性和顺序性,TCP数据包可以保证发送到物理网络接口的数据包的顺序性。如果网络接口接收到的数据包乱序,网络适配器和操作系统将确保它们以正确的顺序重新组合以供应用程序使用。常见的基于TCP的StreamSocket就是我们经常访问的http和https服务。处理http和https服务的服务器一般是nginx或者apache,所以通常有如下的StreamSocket地址:124.225.141.53:80124.225.141.53:443我上面用的是网易的ip地址,其中80表示http,443表示https。使用socat创建TCP服务器。常用的TCP服务器可以选择apache或者nginx。这里为了简单起见,我们选择使用socat来创建一个TCP服务器。什么是socat?它是SOcketCAT的缩写,可以用来模拟一个TCP服务器。socat的命令非常复杂,这里简单介绍一下它的应用:socat-hsocatbyGerhardRiegerandcontributors-seewww.dest-unreach.orgUsage:socat[options]fromabove从结果我们可以看出,socat可以接受一些地址,然后添加一些选项。这里我们使用socat创建两个连接,TCP6和TCP4,socat有两个选项来完成这项工作:tcp-connect::groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCPtcp-listen:<端口>groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCPtcp4-connect::groups=FD,SOCKET,CHILD,RETRY,IP4,TCPtcp4-listen:groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,TCPtcp6-connect::groups=FD,SOCKET,CHILD,RETRY,IP6,TCPtcp6-listen:groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,TCP这里我们只需要创建两个监听TCP的服务,所以我们使用如下命令:socatTCP4-LISTEN:8888,fork/dev/null&socatTCP6-LISTEN:8888,ipv6only=1,fork/dev/null&以上命令,我们在8888端口监听TCP4和TCP6的连接信息,其中fork参数表示程序收到包后继续运行,如果不使用fork,程序会自动退出。socat之后本来连接了一个双向地址,这里我们使用/dev/null,意思是丢弃所有的收入信息。TCP6-LISTEN有一个特殊的参数叫ipv6only,意思是接收到的数据包不应该发送到IPv4映射的IPv6地址。什么是IPv4映射的IPv6地址?简单来说,IPv4映射到IPv6地址。执行上面的命令,我们会得到如下输出:[1]30877[2]30885因为它是在后台执行的,所以我们返回进程的ID。使用ss查看TCP连接ss是一个非常强大的命令,我们可以使用ss来监控TCP套接字的信息,它的用法如下:ss-h用法:ss[OPTIONS]ss[OPTIONS][FILTER]我们主要看以下将使用的几个参数:-4,--ipv4仅显示IP版本4套接字-6,--ipv6仅显示IP版本6套接字-t,--tcp仅显示TCP套接字-l,--listening显示listeningsockets-n,--numeric不解析服务名因为我们只监听ipv4和ipv6数据,所以这里使用-4和-6这两个参数。另外,因为只需要监听tcpsockets,所以需要使用-t参数。因为是监听,所以使用-l参数。最后,我们希望看到具体的数字,而不是被解析成服务名,所以这里使用了-n参数。我们用下面的命令看看结果:ss-4-tln结果如下:StateRecv-QSend-QLocalAddress:PortPeerAddress:PortLISTEN05*:8888*:*表示8888端口是被监控到,当然如果你服务器上还有其他进程的话,可能不止这条数据。上面的命令只监听Ipv4,我们再来看Ipv6:ss-6-tln可能得到如下输出:ss-6-tlnStateRecv-QSend-QLocalAddress:PortPeerAddress:PortLISTEN05:::8888:::*和Ipv4很像,说明我们在Ipv6上监听了8888端口。使用nc连接socket我们已经建立了一个监听TCP连接的服务器,接下来我们尝试使用nc命令进行连接。nc是Ncat的缩写,是一个非常有用的网络工具,可以做很多事情。让我们来看看这个例子中将使用的参数:-4UseIPv4only-6UseIPv6only-v,--verbose设置冗长级别(可以多次使用)-z零I/O模式,报告连接状态只需要-4和-6参数,因为它需要连接Ipv4和Ipv6。另外,我们需要输出详细的信息,所以需要-v参数。最后我们直接建立连接,不发送任何数据,所以这里使用-z参数。让我们执行它看看效果:nc-4-vz127.0.0.18888看看下面的输出:nc-4-vz127.0.0.18888Ncat:Version7.50(https://nmap.org/ncat)Ncat:连接到127.0.0.1:8888.Ncat:发送0个字节,在0.01秒内接收到0个字节。可以看到nc成功建立了连接,发送了0字节的内容。同样,我们建立到IPv6的连接:nc-6-vz::18888其中::1表示IPv6的本地地址。输出结果如下:Ncat:Version7.50(https://nmap.org/ncat)Ncat:Connectedto::1:8888。Ncat:发送0个字节,在0.01秒内接收到0个字节。综上所述,我们介绍了SocketStreamSocket基本分类的含义,并利用unix中的工具搭建了socket服务器端和客户端。当然,这只是最简单的描述,大家可以用它来体验一下StreamSocket的过程。本文已收录于http://www.flydean.com/15-stream-socket/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等着你去探索!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!