端口号
端口号(Port)标识了一个主机上的不同进程,在TCP/IP协议中用 "源IP","目的IP","源端口号","目的端口号","协议号"这样一个五元组来标识一个通信(可以通过 netstat -n 查看)
端口号范围划分
-
0-1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的,如果我们自己写的客户端要设置知名端口号,需要root权限,不过这一般是不允许的。
-
1024-65535:操作系统动态分配的端口号,客户端程序的端口号就是由操作系统从这个范围分配的。
认识知名端口号
比如:
-
ssh服务器,使用22端口号
-
ftp服务器,使用21端口号
-
telnet服务器,使用23端口号
-
http服务器,使用80端口
-
https服务器,使用443端口
在linux上可以查看配置文件,查看知名端口号
vim /etc/services
两个问题
一个进程是否可以bind多个端口号?
可以
一个端口号是否可以被多个进程bind?
不可以,因为我们需要保证端口号到服务进程之间的唯一性
netstat命令
netstat(Network Statistics)是一个常用的命令行工具,用于显示网络连接、路由表、接口统计信息以及网络协议的使用情况。
常见的netstat命令选项
-
netstat -a:显示所有的网络连接。
-
netstat -t:显示所有的TCP 连接。
-
netstat -u:显示所有的UDP 连接。
-
netstat -l:仅显示监听中的端口。
-
netstat -n:显示数字格式的IP地址和端口号,而不是主机名和服务名(提高显示速度)。
-
netstat -p:显示与每个连接相关的进程ID和程序名(需要root权限)。
这些命令可以组合使用,例如: netstat -altp
UDP协议
UDP协议端格式
-
16位UDP长度,表示整个数据报(报头+有效载荷)的最大长度
-
如果校验和出错,就会直接丢弃
UDP的报头是一个结构体,任何协议要解决两个子问题
如何将报头和有效载荷进行分离(封装)?
UDP采用定长报头,报头的大小是确定的,而且,报头中有16位UDP长度,长度减去报头就是有效载荷了,这样就可以分离报头和有效载荷了
如何将有效载荷进行分用?
根据报头的16位目的端口号,找到对应的服务进程,然后进行数据的处理
UDP的特点
-
无连接:知道对方的IP和端口号就直接进行传输,不需要建立连接
-
不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息
-
面向数据报:不能够灵活的控制读写数据的次数和数量
面向数据报
应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并
用UDP传输100个字节的数据:
-
如果发送端调用一次sendto,发送100个字节,那么接收端也必须调用对应的一次recvfrom接收100个字节,而不能循环调用10次recvfrom,每次接收10个字节
UDP的缓存区
-
UDP 没有真正意义上的发送缓冲区 ,调用 sendto 会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作
-
UDP 具有接收缓冲区, 但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了, 再到达的 UDP 数据就会被丢弃
UDP的socket既能读,也能写,这个叫做全双工
UDP的使用注意事项
我们注意到,UDP协议首部有一个16位的UDP长度,也就是说一个UDP能传输的数据最大长度是64K(包括UDP首部)如果我们需要传输的数据超过64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装。
基于UDP的应用层协议
-
NFS:网络文件系统
-
TFTP:简单文件传输协议
-
DHCP:动态主机配置协议
-
BOOTP:启动协议(用于无盘设备启动)
-
DNS::域名解析协议
进一步理解UDP协议
关于UDP报文的序列化和反序列化,从传输层到另一个传输层是结构体——二进制——结构体
用的是二进制流的序列化和反序列化,因为传输层是属于操作系统的,而操作系统都是用C语言写的,在代码上具有统一性,所以结构体转成二进制,不会有语言上的差别,而在应用层,可能是两种不同语言的应用层传输,所以不建议转为二进制进行传输
对报文的理解
OS内可能同时存在大量报文,正在向上交付或者正在向下传递所以OS需要对报文进行管理————先描述,再组织!!!
struct sk_buff——管理报文