上篇博文从应用层面解释了什么是端口:网络通信都是在socket之间进行的,socket中的IP用于定位计算机,socket中的端口号用于定位计算机中的程序。
绝大多数需要进行网络通信的程序都会有相应的端口号,但注意我说的是“绝大多数”,而不是“所有”。比如我们经常使用的ping命令,就是一个不需要端口号的网络程序。那为什么有的网络程序需要端口,而有的又不需要呢?
下面就从理论层面再进一步解释什么是端口。
说到理论,就要牵扯到网络模型。我们都知道,网络模型主要有OSI的7层模型以及TCP/IP的4层模型,不过在实际使用时,我们往往都是把它们组合成一个5层模型。
在这个5层模型中,我们关注的主要是上三层:应用层、传输层、网络层。
在每一层中都有很多协议,网络协议其实就是制定了一种规则,想要实现某种功能,那么就得遵循这种规则。比如Web服务就得遵循HTTP协议的规则,域名解析服务就得遵循DNS协议的规则等。
我们平时使用的绝大多数网络程序,它们所遵循的协议都是位于应用层,而应用层就要跟传输层打交道。
传输层的协议只有两个:TCP和UDP。而应用层的程序则是多种多样,所以这就带来一个问题:传输层的协议如何区分它所接收到的数据到底是对应了应用层的哪个程序?
端口就是为了解决这个问题而引入的。所以在理论层面,端口是一个传输层的概念,它是应用层的程序与传输层的TCP或UDP协议之间联系的通道。
每个端口都对应着一个应用层的程序,当一个应用程序要与远程主机上的应用程序通信时,传输层协议就为该应用程序分配一个端口。端口号是唯一的,不同的应用程序有着不同的端口,以使彼此的数据互不干扰。
需要注意的是,由于端口号是由传输层的TCP或UDP协议给应用层的程序分配的,所以在表示端口号时,应当标明这是一个TCP端口还是UDP端口。比如Web服务使用的是TCP80端口,SSH服务使用的是TCP22端口,DNS服务使用的是UDP53端口等。
在使用netstat命令查看端口状态时,左侧第一列就是标明了端口所对应的传输层协议。
当然,由于大多数应用层程序在传输层都是选择使用TCP协议,所以大部分端口号也都是TCP端口。平常使用时,我们可能会习惯性地忽略掉TCP,而直接称呼80端口、22端口,但这其实并不是一种严格的说法,端口的标准表示方式应该是TCP80、TCP22。
最后再解释一下在本文开头提出的问题:为什么像ping命令这类网络程序不需要端口号呢?
原因其实很简单,因为ping命令使用的是网络层的ICMP协议,而网络层在传输层之下,所以ping命令的数据不需要经过传输层的处理,这样自然就不需要为其分配端口号了。
同样的道理,数据链路层的ARP协议也不需要端口号。但这类程序毕竟是少数,我们平时使用的绝大多数网络程序都是位于应用层,因而都会有相应的端口号。
最后小结一下:端口是一个传输层的概念,是由传输层的TCP或UDP协议给应用层的程序分配的。我们在表示端口时,最好标明这是一个TCP端口还是一个UDP端口。