端口号标识了一个主机上进行通信的不同的应用程序。
在TCP/IP协议中,用“源IP”,“源端口号”,“目的IP”,“目的端口号”,“协议号”这样一个五元组来标识一个通信。
0-1023:知名端口号,广为使用的应用层协议,他们的端口号都是固定的。
1024-65535:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围里面分配的。
ssh服务器 22号端口
ftp服务器 21号端口
telnet服务器 23号端口
http服务器 80号端口
https服务器 443号端口
netstat
安装:yum -y install net-tools
参数: |
-a 显示所有选项,默认不显示LISTEN相关 |
-t 仅显示tcp相关选项 |
-u 仅显示upd相关选项 |
-n 拒绝显示别名,能显示数字的全显示数字 |
-l 显示监听的服务状态 |
netstat 的基本使用_netstat的使用_你有些许优秀的博客-CSDN博客
pidof
查看服务器的进程id
pidof [进程名字]
xargs
将标准输入的内容,转换为命令行参数。
搭配管道使用,因为管道是标准输入,输入内容在命令行使用时需要进行转换。
pidof procname | xargs kill -9
先来解决两个问题
一、报头如何分离(封装)?
UDP中报头的长度是固定的,为8字节。报头中华有16位的UDP长度,是整个报文的长度,有效载荷的字节数需要拿这个值减去报头长度,即-8。
正是因为16位的UDP长度,使得每次UDP传输时,都可以确切的知道报文的长度,也就确保我们可以正确的提取整个完整的报文。因此,UDP具有将报文一个一个接收的能力,即UDP是面向数据报的。
二、如何交付?
报头中有16位的端口号,向上交付的时候,进程可以根据这个端口号进行bind
strcut udp_hdr
{uint32_t src_port:16;uint32_t dst_port:16;uint32_t udp_length:16;uint32_t udp_check:16;
}
本质就是一个位段。
当收到一个报文的时候,只需要将起始位置强转为(struct udp_hdr*)start,然后去访问各个成员。
start->src_port; //...
先来回答一个问题
sendto/recvfrom/write/read等系统调用的IO接口,真的是在网络中进行接收/发送数据的吗?
不是,他们本质上都是拷贝函数。
用户层下层就是传输层。传输层顾名思义是用来进行数据传输的。
也就是说,接收/发送消息都是传输层帮我去做的。就像发快递一样,你只是把快递给了快递员,具体的流程是快递公司帮你做的。
UDP没有真正意义上的发送缓冲区,调用sendto时会直接交给内核,由内核将数据传给网络层协议,然后进行后续的传输动作。
UDP具有接收缓冲区。但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致,如果缓冲区满了,再到达UDP数据就会被丢弃。
UDP的socket既能读,也能写,这个概念叫全双工。
UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部).
然而64K在当今的互联网环境下, 是一个非常小的数字.如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装;
NFS: 网络文件系统。
TFTP: 简单文件传输协议。
DHCP: 动态主机配置协议。
BOOTP: 启动协议(用于无盘设备启动)。
DNS: 域名解析协议。
当然, 也包括你自己写UDP程序时自定义的应用层协议。