1.再谈端口号
1.1复习
我们上一篇谈了很久的应用层的http,并在此前我们使用socket编程写了一个能相互通信的客户端与服务端,但是我们也只是粗略的理解了一下tcp和udp在编程过程中所形成的差异性,并没有实质去了解一下其详细内容,那么这篇文章就来详细介绍一下传输层协议用到的udp协议,当然其他协议我们会在后面为大家一一讲解
1.2端口号
端口号用于标识一台主机上唯一的进程。(前面文章具体提到过)
当主机从网络上获取数据之后 ,这个数据要交给哪个应用程序就是由端口号决定的。
在网络通信中,数据在向上层进行交付时,传输层协议(如TCP或UDP)会提取出数据报文中的目的端口号。目的端口号指示了应该将数据交付给当前主机上的哪个服务进程。
实际上通过端口号能找到的是我们的进程ID的,其原因是因为内核中用哈希的方式维护了端口号与进程ID之间的映射关系,传输层可以通过端口号得到对应的进程ID 进而找到对应的应用层进程。
1.3端口号范围划分
-
0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的。
-
1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。
有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:
ssh服务器, 使用22端口
ftp服务器, 使用21端口
telnet服务器, 使用23端口
http服务器, 使用80端口
https服务器, 使用443
平常我们自己写端口号的时候需要尽量避免这些端口号。
1.4五元组
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信。
通过netstat命令可以查看到这样的五元组信息:
-
Proto – 协议号
-
Local Address – 源IP地址和源端口号
-
Foreign Address – 目的IP地址和目的端口号
netstat是一个用来查看网络状态的重要工具 其常见的选项如下:
-
n:拒绝显示别名 能显示数字的全部转换成数字
-
l:仅列出处于LISTEN(监听)状态的服务
-
p:显示建立相关链接的程序名
-
t(tcp):仅显示tcp相关的选项
-
u(udp):仅显示udp相关的选项
-
a(all):显示所有的选项 默认不显示LISTEN相关
pidof命令 在查看服务器的进程id时非常方便.
语法:pidof [进程名]
功能:通过进程名, 查看进程id
当然这里提到了协议号,这里简单介绍一下其定义:
协议号是网络通信中用于标识不同网络协议的数字。每个网络协议都会被分配一个唯一的协议号,以便在数据包传输过程中能够正确地识别和路由数据。
-
2.UDP协议
2.1udp协议端格式
- 16位源端口号表示数据从哪里来
- 16位目的端口号标识数据要去哪里
- 16位UDP长度:表示整个数据报(UDP首部+UDP数据)的长度
- 16位UDP检验和:如果UDP报文的检验和出错 就会直接将报文丢弃
我们在应用层看到的端口号大部分都是16位的 其根本原因就是因为传输层协议当中的端口号就是16位的
2.2报头与有效载荷的分离
UDP的报头当中只包含四个字段, 每个字段的长度都是16位, 总共8字节。
因此UDP采用的实际上采用的是一种定长报头, UDP在读取报文时读取完前8个字节后剩下的就都是有效载荷了。
2.3udp的数据封装与解包
-
当应用层将数据交给传输层后 ,在传输层就会创建一个UDP报头类型的变量,然后填充报头当中的各个字段 ,此时就得到了一个UDP报头。
-
此时操作系统再在内核当中开辟一块空间 ,将UDP报头和有效载荷拷贝到一起 ,此时就形成了UDP报文。
-
当传输层从下层获取到一个报文后 ,就会读取该报文的前8个字节, 提取出对应的目的端口号。
-
通过目的端口号找到对应的上层应用层进程 ,然后将剩下的有效载荷向上交付给该应用层进程。
2.4udp协议的特点
-
无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
-
不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层
返回任何错误信息;
-
面向数据报: 不能够灵活的控制读写数据的次数和数量;
应用层交给UDP多长的报文 ,UDP就原样发送, 既不会拆分 ,也不会合并, 这就叫做面向数据报。
也就是说我们如果使用UDP传输一百字节的数据的话:
如果我们发送端调用了十次sendto, 发送100字节的数据 ,每次发送十字节 ,那么接收端也必须调用十次recvfrom来接受这100字节的数据。
2.5udp的缓冲区
为什么会造成上述的这种面向数据报的特性呢?
因为UDP没有真正意义上的 发送缓冲区, 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后
续的传输动作;
但是UDP具有接收缓冲区。可这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果
缓冲区满了, 再到达的UDP数据就会被丢弃。
UDP的socket既能读, 也能写, 这个概念叫做 全双工。
2.6udp的使用注意事项
需要注意的是 UDP协议报头当中的UDP最大长度是16位的, 因此一个UDP报文的最大长度是64K。(包含UDP报头的大小)
然而64K在当今的互联网环境下 ,是一个非常小的数字 ,如果需要传输的数据超过64K, 就需要在应用层进行手动分包 ,多次发送, 并在接收端进行手动拼装。
2.7基于udp的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
当然 ,也包括你自己写UDP程序时自定义的应用层协议。