从通信原理角度看待socket对UDP包的解析
扫描二维码
随时随地手机看文章
UDP协议特点
1.无连接:UDP不需要建立连接,直接发送数据包。
2.不可靠:不保证数据包顺序、不保证送达,可能丢包。
3.面向数据报:每个UDP数据包都是一个独立的消息,有明确的边界。
SIP协议与UDP
SIP协议可以运行在多个传输层协议上,包括UDP、TCP、TLS等。由于UDP简单高效,很多SIP实现采用UDP。但UDP的不可靠性和无连接性要求应用层处理以下问题:
1. 消息重传:对于重要的请求(如INVITE),如果没有收到响应,需要重传。
2. 消息分片:UDP数据包有最大长度限制(通常受MTU影响),如果SIP消息太大,需要分片(但在SIP中通常避免大消息,或者使用TCP传输大消息)。
3. 乱序处理:UDP数据包可能乱序到达,应用层需要根据SIP消息中的序列号(如CSeq)进行排序或处理。
Socket 接收流程
(1) 网络接口层 (NIC):物理网卡接收以太网帧;校验帧完整性(CRC32);剥离帧头,将 IP 包传递给网络层
(2) IP 层处理:解析 IP 头部(源 IP、目的 IP、协议类型);检查目的 IP 是否匹配本机;根据协议类型(UDP=17)传递给传输层
(3) UDP 层处理:解析 UDP 头部(源端口、目的端口);根据目的端口号查找对应的 Socket;计算校验和验证数据完整性
(4) Socket 接收队列:内核将 UDP 数据包放入 Socket 接收缓冲区;应用层通过 recvfrom() 系统调用读取数据。
在Go中解析UDP包上的SIP消息
1.监听UDP端口:通过`net.ListenUDP`创建UDP套接字,绑定到指定端口。
2.读取数据报:使用`ReadFromUDP`方法读取一个完整的UDP数据报。每个数据报包含一个完整的SIP消息(或者分片的一部分,但SIP通常避免分片)。
3.解析SIP消息:将读取到的字节数组(`[]byte`)解析为SIP消息结构。解析过程包括:
- 解析起始行(请求行或状态行)。
- 解析头部字段(每个头部字段以`\r\n`分隔,头部与消息体之间以空行`\r\n\r\n`分隔)。
- 解析消息体。
实现一个简单的SIP解析器
1. 将字节数组按行分割(`strings.Split(string(data), "\r\n"`)。
2. 解析起始行:对于请求,格式为`方法 SP 请求URI SP SIP版本`;对于响应,格式为`SIP版本 SP 状态码 SP 原因短语`。
3. 解析头部:逐行读取直到遇到空行。每行是一个头部字段,格式为`字段名:字段值`。注意处理多行字段(以空格或制表符开头)。
4. 解析消息体:剩余部分就是消息体,长度由`Content-Length`头部指定(如果没有Content-Length,则消息体直到数据包末尾)。