一、简述与回顾
传输层:负责数据能够从发送端传输接收端
在TCP/IP协议中,我们用"源IP","源端口号","目的IP","目的端口号",和"协议号"来表示一个通信。
- ip地址是用来在网络上标识唯一一台主机的
- 端口号是用来表示主机上唯一一个进程的
- 这里的"协议号"是用来表明用的是哪个协议(TCP/UDP/...)进行通信的
注意:一个进程能对应多个端口号,一个端口号只能对应一个进程
端口号范围划分:
- 0 - 1023:知名端口号HTTP, FTP,SSH等这些广为使用的应用层协议, 它们的端口号都是固定的
- 1024 - 65535:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的
知名端口号:
- ssh服务器, 使用22端口
- ftp服务器, 使用21端口
- telnet服务器, 使用23端口
- http服务器, 使用80端口
- https服务器, 使用443
cat /etc/services // 用来查看知名端口号 --- 自己写的程序使用端口号,尽量避开这些端口号
netstat命令
netstat是一个用来查看网络状态的重要工具
语法:netstat [选项]
功能:查看网络状态
常用选项:
- n 拒绝显示别名,能显示数字的全部转化成数字
- l 仅列出有在 Listen (监听) 的服務状态
- p 显示建立相关链接的程序名
- t (tcp)仅显示tcp相关选项
- u (udp)仅显示udp相关选项
- a (all)显示所有选项,默认不显示LISTEN相关
还有一个ss命令,和netstat用法差不多,也是用来查看网络状态的,大家可以试试
pidof命令
在查看服务器的进程id时非常方便.
语法:pidof [进程名]
功能:通过进程名,查看进程id
二、UDP
1、UDP协议端格式
从上图我们就能理解在网络套接字编程中的部分操作
- 在应用层写完数据后调用sento函数进行发送,本质就是将数据拷贝到UDP报文的数据区中,以及sendto函数中要传服务器的sockaddr结构体,是因为udp协议需要填写目的端口号
- 端口号用16位整形接收是因为底层的udp协议规定的16位
当然协议的定制还有两个问题需要处理:
1、如何将报头和数据分离?
在udp协议中,报头字段的大小是固定的8字节,同时16位UDP长度表示整个报文的大小,所以我们能很轻易的将报文进行拆分,同时判断出报文是否完整 --- 如果报文长度小于8字节或小于报文中记录的报文长度,说明报文不全
2、如何向上交付数据?
通过目的端口号,可以找到需要交付数据的进程
注意:16位校验和是用来检验数据是否被修改,主要是通过数学运算,有兴趣可以自行去了解一下,如果校验和出错,就会直接丢弃
2、如何理解报头?
3、UDP的特点
UDP传输的过程类似于寄信
- 无连接:知道对端的IP和端口号就直接进行传输,不需要建立连接
- 不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息;
- 面向数据报:不能够灵活的控制读写数据的次数和数量
如何理解面向数据报?
- 发送方应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
- 接收放在收到报文后,必须一次读完一整个UDP报文,不能将一个UDP报文分开来读。
如何理解UDP的缓冲区?
- UDP没有真正意义上的 发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作
- UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致。如果缓冲区满了,再到达的UDP数据就会被丢弃
这里的缓冲区可以看成是上图中struct sk_buffer组成的链表队列
UDP的socket既能读,也能写,这个概念叫做 全双工
注意点:UDP的报头中有一个报文长度字段,表明UDP报文的长度最大位64KB,如果需要发送的数据大于64KB,就需要我们手动多次发送
4、基于UDP的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
当然,也包括你自己写UDP程序时自定义的应用层协议