多路复用和多路分解
在上一篇文章 计算机网络之传输层浅析 中讲到负责收发邮件的那两个老六,它就还比是 Socket
,邮政服务为两个家庭提供逻辑通信,看似信件是由两家人互相寄出的,而其实是通过邮政服务传递的。
在目的主机,传输层从紧邻其下的网络层接收报文段,传输层负责将这些报文段中的数据交付给在主机上运行的适当应用程序进程。
一个进程有一个或多个套接字(Socket
),它相当于从网络向进程传递数据和从进程向网络传递数据的门户。
实际上,在接收主机中的传输层并没有直接将数据交付给进程,而是将数据交给了一个中间的套接字,由于在任一时刻,在接收主机上可能有不止一个套接字,在接收主机上可能不止一个套接字,所以每个套接字都有唯一的标识符。
-
多路复用: multiplexing
- 在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层;
- 将多个数据流合并为一个数据流;
-
多路分解: demultiplexing
- 在接收端,传输层检查这些字段,标识出接收套接字,进而将报文段定向到该套接字,将传输层报文段中的数据交付到正确的套接字的工作称为多路分解;
- 多路复用的逆过程,将数据流分离成单独的部分;
在我们实际上使用的微信或其他社交软件,当我们发送一个 hello
,经过的过程可多了,它是一个封装和解封装的过程,请看下面的动图:
在这整个过程中,发送端就是不断的给数据添加报头发送给它的上一层,最终将其转为字节流传送给接收端的物理层上,在接收端中不断对其解封装,最终显示信息在对方的社交软件上。
为了更好的说明分解的工作过程,再回顾一下这篇文章中讲到的家庭类比 计算机网络之传输层浅析。
每一个孩子的通过他的名字来表示,当接收到邮政员送来的一批信件时,并通过查看收信人名字而将信件亲手交付给他的兄弟姐妹们时,他执行的就是一个分解操作。而当他收集所有兄弟姐妹们的信件并交给邮政员的时候,这个过程就是一个多路复用操作。
如何实现多路复用
通过上面的内容,我们知道运输层多路复用有以下要求:
- 套接字有唯一的标识符;
- 每个报文段有特殊字段来指示该报文段所要交付到的套接字;
如上图所示,这些特殊字段是源端口号和目的端口号,端口号是一个16比特的数,其大小在 0 ~ 65535
之间,其中 0 ~ 1023
是周知端口号(保留给例如HTTP
、FTP
、SMTP
等周知应用层协议使用,其中HTTP
使用的是80端口)。
在主机上的每个套接字能够分配一个端口号,当报文段到达主机时,传输层检查报文段中的目的端口号,并将其定向到相应的套接字。然后当报文段到达主机时,传输层检查到报文段中的目的端口号,并将其定向到相应的套接字。然后报文段中的数据通过套接字进入其所链接的进程。
无连接的多路复用与多路分解
一个 UDP
套接字是由一个二元组全面标识的,该二元组包含一个目的 IP
地址和一个目的端口号。因此,如果两个 UDP
报文段有不同的源 IP
地址或源端口号,但具有相同的目的 IP
地址和目的端口号,那么这两个报文段将通过相同的目的套接字被定向到相同的目的进程。
发送端的传输层会创建一个传输层报文段,其中包括应用程序数据、源端口号(66666)、目的端口号(77777)和两个其他值。然后传输层将得到的报文段传递给网络层。
网络层将该报文段封装到一个 IP
数据报中,并尽力而为地将报文段交付给接收主机。这个就是前面的以太网封装动图中的封装过程。
如果该报文段到达接收端,接收主机运输层就检查该报文段中的目的端口号并将该报文段交付给端口号(77777)所标识的套接字,这样就完成了一个多路分解操作了。
面向连接的多路复用与多路分解
TCP
套接字和 UDP
套接字之间的一个细微差别是,TCP
套接字是由一个四元组组成的,它们分别是源IP地址、源端口号、目的IP地址、目的端口号来标识的。因此当一个 TCP
报文段从网络到达一台主机时,该主机使用全部4个值来将报文段分解到相应的套接字。
和 UDP
不同的是,两个具有不同源 IP
地址或源端口号的到达 TCP
报文段将被定向到两个不同的套接字,除非 TCP
报文段携带了初始创建连接的请求。
接下来我们通过5点来了解一下 TCP
的通信过程:
TCP
服务器端有一个欢迎socket
,等待从客户端来的连接建立请求;TCP
客户端建立一个socket
,并将这个socket
与服务器相连;- 一条连接建立请求就是第一个
TCP
段,包含目的端口号和特殊的连接建立位置位的报文段,也包含源端口号; - 当服务器收到连接建立请求,就创建一个专门的通信
socket
负责这两个进程的通信; - 服务器的传输层注意到连接请求报文段中的四元组,如果后续到达的报文段和这个四元组匹配,则被分配到相同的套接字,随着
TCP
连接完成,这两端也就可以相互发送数据了;
请看上图,主机A和主机C分别向服务器发送了两个 HTTP
对话和一个 HTTP
对话,尽管主机A和主机C的源端口想用,但是对于服务器B来说依旧能够正确地分解这个两个具有相同源端口号号来连接,因为这两条连接有不同的源 IP
地址。
端口号如何确定
在实际进行通信时,要实现确定端口号,确定端口号的方法分为两种,它们分别是标准既定的端口号和时序分配法。
标准既定的端口号
这种方法也叫静态方法,它是每个应用程序都有指定的端口号,但并不是说可以随意使用任何一个端口号,每个端口号都有其对应的使用目的。
例如 HTTP
、TELNET
、FTP
等广为使用的应用协议中所使用的端口号就是固定的,这些端口号也被称为致命端口号,除了这些知名端口号之外,还有一些端口号也被正式注册,它们分布在 1024
到 49151
的数字之间,不过这些端口号可用于任何通信用途。
时序分配法
第二种方法也就时序或者动态的分配法。此时服务端有必要确定监听端口号,但是接收服务的端口号没必要确定端口号。
在这种方法下,客户端应用程序可以完全不用自己设置端口号,而全权交给操作系统进行分配。操作系统可以为每个应用程序分配互不冲突的端口号,例如每需要一个新的端口号时,就在之前分配号码的基础上加1,这样操作系统就可以动态地管理端口号了。
结束了,不总结了,下一篇讲 UDP
,紧接着是 TCP
,传输层太多东西了,几篇篇文章根本写不完。
参考文献
- 书籍:
图解TCP/IP
; - 书籍:
计算机网络原书第七版
;
本文正在参加「金石计划」
原文链接:https://juejin.cn/post/7214805603448848443 作者:Moment