讲完网络层(IP层),接下来开始介绍传输层。传输层主要有两个协议:TCP 协议和 UDP 协议。TCP 提供面向连接的可靠性传输,UDP 则提供面向无连接的非可靠性传输。
传输层的定义及通信处理
我们前面介绍 IP 报文首部格式的时候提到其中有一个协议字段(Protocol),用来标识网络层的上一层所采用的是哪一种传输层协议,根据这个字段的协议号就可以识别 IP 传输的数据部分究竟是 TCP 的内容还是 UDP 的内容。
同样,传输层的 TCP 和 UDP,为了识别自己所传输的数据部分究竟是应该发送给应用层的哪个应用,也设定了这样的一个编号。
网络层可以根据 IP 地址将数据包发送到指定主机,但是到达目标主机后该由哪个应用程序来处理呢?这个就是传输层干的事情,传输层使用端口号这种识别码识别在传输层上一层的应用层中所要进行处理的具体程序。
TCP/IP 的众多协议大多以客户端/服务端的形式运行,客户端是请求的发起方,而服务端是请求的处理端。另外,作为服务端的程序有必要提前启动,准备接收客户端的请求,否则客户端的请求过来,无法进行相应的处理。以下是一个 TCP 请求的简化流程:
这些服务端程序在 UNIX 系统中叫守护进程,例如 Nginx、PHP-FPM、MySQL、Redis 等后台服务都是守护进程。
确认一个请求究竟发送给哪个服务端程序,可以通过所收到数据包的目标端口号进行识别。例如,当收到 TCP 的建立连接请求时,如果目标端口号是 80,则转给 Nginx/Apache,然后 Nginx/Apache 会继续对该连接上的通信传输进行处理,比如如果请求的是静态资源则可以直接返回,如果是动态请求需要继续转发给相应的 CGI 处理程序进行处理,比如 PHP-FPM。
传输协议 TCP 和 UDP 都是通过接收数据中的目标端口号识别目标处理程序。
端口号定义及设置
数据链路和网络层中的地址,分别指的是 MAC 地址和 IP 地址,前者用来识别同一链路中的不同计算机,后者用来识别计算机网路中互连的主机和路由器。在传输层中也有类似于地址的概念,那就是端口号,端口号用来识别同一台计算机中进行通信的不同应用程序,因此,它也被称为程序地址。
一台计算机可以同时运行多个程序,例如浏览器、电子邮件客户端、PhpStorm、QQ等,传输层正是利用端口号识别本机中正在运行的程序,并准确进行数据传输。实际上,通过源 IP 地址、目标 IP 地址、协议号(TCP/UDP)、源端口号、目标端口号这五个信息就可以唯一识别一个通信,五项中任何一个字段值不同,就被认为是不同的通信:
在实际进行通信时,需要事先绑定端口号。端口号的有效范围介于 0~65535 之间。确定端口号的方式分为两种:
- 标准既定的端口号(静态方法):每个应用程序都有指定的端口号,但也不是任意指定,其中低于 1024 的端口号一般是系统预留的知名端口号,比如 HTTP 端口号一般是 80,SSH 端口号一般是 22,FTP 端口号一般是 21,SMTP 端口号一般是 25 等等。除此之外,还有一些端口号也被正式注册,它们分布在 1024 到 49151 之间,比如 MySQL 端口号是 3306,Redis 端口号是 6379,Memcache 端口号是 11211。关于知名端口号和注册端口号的最新信息,请查看这里:https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml。
- 时序分配法(动态方法):服务端必须确定监听端口号,但是客户端不需要确定端口号,可以交由操作系统动态分配,操作系统可以为每个应用程序分配互不冲突的端口号,系统分配的端口号范围介于 49152 到 65535 之间。
我们在编写自己的服务端应用程序设置监听端口号时,一般只需要高于 1024 并避开系统已安装的其它应用程序已经注册的端口号即可。
了解了传输层的基本定义和端口号设置后,接下来,将就 UDP 协议、TCP 协议以及套接字(Socket)编程三个方面展看,帮助大家进一步理解传输层。