本文将介绍TCP/IP四层结构模型中的传输层。
🍅传输层
传输层主要负责将数据从发送端传输到接收端。
🍋再谈端口号
我们之前已经知道,端口标识的是一个主机上进行的应用程序。
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n
查看);
🥝netstat指令
netstat是一个用来查看网络状态的重要工具.
- 语法:netstat [选项]。
- 功能:查看网络状态。
- 常用选项:
- -n:拒绝显示别名,能显示数字的全部转化成数字
- -l:仅列出有在 Listen (监听) 的服務状态
- -p:显示建立相关链接的程序名
- -t : (tcp)仅显示tcp相关选项
- -u :(udp)仅显示udp相关选项 -a (all)显示所有选项,默认不显示LISTEN相关
[lyl@VM-4-3-centos 2022-6-3]$ netstat -n
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 52 10.0.4.3:22 43.227.138.73:2594 ESTABLISHED
tcp 0 0 10.0.4.3:58924 169.254.0.138:8086 ESTABLISHED
tcp 0 0 10.0.4.3:51368 59.36.128.183:9988 ESTABLISHED
上面的列表依次为协议类型、接收队列、发送队列、本地网络的IP和端口号、远端网络的IP和端口号。其中关于接收队列,我们之前编写socket编程时监听listen中参数backlog就代表接收等待队列的最大值。
- 指令:pidof
- 功能:通过进程名查看服务器进程id。
- 语法:pidof [进程名]
[lyl@VM-4-3-centos 2022-6-1]$ pidof http_server
27345
🥝端口号划分范围
我们知道端口号是一个16位的短整型,因此其取值范围是0-65535.而端口号根据其取值可分为:
- 0 - 1023:知名端口号。HTTP、FTP、SSH这些广为人知的应用层协议,它们的端口号是固定的。
- 1024 - 65535:操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。
🥝常见的知名端口号(Well-Know Port Number):
有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:
- ftp服务器:使用21号端口。
- ssh服务器:使用22号端口。
- telnet服务器:使用23号端口。
- http服务器:使用80号端口。
- https服务器:使用443号端口。
服务器的端口号被放在/etc/services
这个文件下,我们可以用more /etc/services
这条指令来查看相关知名端口号。并且我们在写一个程序使用端口号时,应避免使用知名端口号。
🍋UDP协议
🥝UDP协议段格式
在介绍UDP协议之前,我们需要先明确两点:
- 1.任何协议都必须能够解决将自己的报头和有效载荷分离的问题。
- 2.任何协议都必须能够将自己的有效载荷交付给上层的哪一个进程。
UDP的协议格式如下:
对于UDP协议而言,其第一点是由定长报头解决的,即8字节的定长报头,能够让UDP协议将自己的报头和有效载荷进行分离。UDP的报头在底层是通过结构体+位段的方式实现的。
而关于第二点则是由UDP定长报头中的16位目的端口号来明确UDP要将自己的有效载荷交付给上层的哪一个进程,而我们之前套接字编程时之所以端口号port都是16位就是这个原因,同时我们bind亦是将端口号填充到UDP协议报文中。
至于16位UDP长度,就是UDP报文的长度即UDP协议的首部加上数据的总长度。另外16位UDP检验和,是为了校验是否出错,比如出现了数据丢包,那么这个UDP报文就会直接被丢弃。
🥝UDP协议的特点
我们之前已经了解过了,UDP协议类似于寄信的过程,发送端只管将数据发送过去,而不在乎数据是否被对端收到。因此UDP协议具有以下特点:
- 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
- 面向数据报(SOCK_DGRAM): 不能够灵活的控制读写数据的次数和数量
🍓面向数据报
面向数据报指的是不能够灵活控制读写数据的次数和数量,即应用层交给UDP多长的报文,UDP会原封不动的发送出去,既不会拆分,也不会合并。
比如说,用UDP传输50个字节的数据:如果发送端调用一次sendto, 发送50个字节, 那么接收端也必须调用对