18. 传输 (Transport)
传输层负责在网络传输上实际传输请求和响应。这包括在面向连接的传输情况下确定用于请求或响应的连接。
核心职责
传输层负责管理传输协议(如TCP、SCTP或其上的TLS)的持久连接,包括向传输层打开的连接。这包括客户端或服务器传输打开的连接,以便连接在客户端和服务器传输功能之间共享。
连接索引:
- 连接由远端的地址、端口和传输协议形成的元组进行索引
- 当传输层打开连接时,此索引设置为目标IP、端口和传输
- 当传输层接受连接时,此索引设置为源IP地址、端口号和传输
连接重用: 建议在最后一条消息通过该连接发送或接收后,将连接保持打开一段实现定义的持续时间。此持续时间应该至少等于元素将事务从实例化带到终止状态所需的最长时间(通常至少为64*T1)。
强制实现要求:
- 所有SIP元素必须实现UDP和TCP
- SIP元素可以实现其他协议
18.1 客户端 (Clients)
18.1.1 发送请求 (Sending Requests)
传输层的客户端负责发送请求和接收响应。传输层的用户将请求、IP地址、端口、传输和可能的TTL(用于多播目的地)传递给客户端传输。
消息大小和传输选择
关键规则:
- 如果请求在路径MTU的200字节内,或者如果它大于1300字节且路径MTU未知,则必须使用拥塞控制传输协议(如TCP)发送请求
- 这可以防止UDP上的消息分段,并为较大的消息提供拥塞控制
- 实现必须能够处理最大数据报包大小的消息(UDP为65,535字节,包括IP和UDP头)
200字节缓冲区的原因:
- 在SIP中,响应可能比请求大
- 这是由于向INVITE的响应添加Record-Route头字段值而发生的
- 有了额外的缓冲区,响应可以比请求大约170字节,并且在IPv4上仍然不会被分段
1300字节阈值:
- 当路径MTU未知时选择1300
- 基于1500字节以太网MTU的假设
Via头字段处理
在发送请求之前,客户端传输必须在Via头字段中插入"sent-by"字段的值。
sent-by字段:
- 包含IP地址或主机名和端口
- 推荐使用FQDN
- 此字段用于在某些条件下发送响应
- 默认端口:UDP、TCP和SCTP为5060,TLS为5061
接收响应的准备
可靠传输:
- 响应通常在接收请求的连接上发送
- 客户端传输必须准备好在用于发送请求的同一连接上接收响应
- 在错误条件下,必须准备好在"sent-by"字段中的源IP地址和端口号上接收传入连接
不可靠单播传输:
- 客户端传输必须准备好在发送请求的源IP地址和"sent-by"字段中的端口号上接收响应
多播:
- 客户端传输必须准备好在发送请求的同一多播组和端口上接收响应
多播使用
发送到多播地址的客户端必须:
- 向其Via头字段值添加"maddr"参数,包含目标多播地址
- 对于IPv4,应该添加值为1的"ttl"参数
- IPv6多播的使用未在本规范中定义
多播的有意限制:
- 主要功能是提供"单跳发现式"服务
- 将请求传递到一组同质服务器
- 只需要处理来自其中任何一个的响应
- 此功能对注册最有用
18.1.2 接收响应 (Receiving Responses)
当收到响应时,客户端传输检查顶部Via头字段值。
验证步骤:
- 如果该头字段值中"sent-by"参数的值与客户端传输配置为插入请求的值不对应,响应必须被静默丢弃
- 如果存在任何客户端事务,客户端传输使用第17.1.3节的匹配程序尝试将响应匹配到现有事务
- 如果有匹配,响应必须传递给该事务
- 否则,响应必须传递给核心(无论是无状态代理、有状态代理还是UA)进行进一步处理
"游离"响应的处理: 这些"游离"响应的处理取决于核心(例如,代理将转发它们,而UA将丢弃)。
18.2 服务器 (Servers)
18.2.1 接收请求 (Receiving Requests)
服务器传输从网络接收请求并将它们传递给传输层的用户(服务器事务或核心)。
接收准备:
- 服务器必须准备好在公开宣传的地址和端口上接收请求
- 对于任何具有公开宣传URI的元素,这些端口和地址必须与该URI中的端口和传输一致
接收流程:
- 从网络接收请求
- 检查Request-URI
- 如果Request-URI包含SIPS URI,或topmost Route头字段值包含SIPS URI,请求必须通过TLS发送
- 服务器传输尝试将请求匹配到服务器事务(使用第17.2.3节的规则)
- 如果匹配,请求传递给该事务进行处理
- 如果不匹配,请求传递给核心,核心创建新的服务器事务
最大缓冲区大小: 接收UDP数据报时,服务器应该使用能够容纳整个响应的缓冲区大小(65,535字节)。
Via处理: 服务器传输必须在顶部Via头字段中添加"received"参数:
- 包含从中接收请求的源IP地址
- 此参数插入即使它与sent-by组件的"host"部分相同
- 对于可靠传输通常不是必需的,但不添加也没有坏处
rport参数: 如果Via头字段值包含"rport"参数:
- 服务器传输必须在该参数中设置其值为从中接收请求的端口
- 这用于NAT穿越
18.2.2 发送响应 (Sending Responses)
服务器传输使用Via头字段值来确定将响应发送到哪里。
发送规则:
1. 可靠传输:
- 响应必须在接收请求的连接上发送
- 如果该连接不再打开,服务器应该打开一个到Via中指示的IP地址和端口的连接
- 如果该连接尝试失败,服务器应该使用RFC 3263的程序确定IP地址和端口
2. 不可靠传输:
- 服务器必须发送响应到Via的"received"参数指示的地址
- 如果"rport"参数存在,响应必须发送到该参数中的端口
- 否则,发送到Via的"sent-by"字段中的端口
特殊情况:
- 如果Via没有"received"参数,发送到"sent-by"字段中的地址
- 如果响应是INVITE的2xx,且Record-Route头字段包含SIPS URI,必须通过TLS发送
18.3 分帧 (Framing)
在面向流的传输(如TCP)上,消息需要分帧以确定消息边界。
分帧机制:
- SIP使用Content-Length头字段来确定消息体的长度
- 消息由起始行、头字段和可选的消息体组成
- 接收器通过读取起始行和头字段来确定Content-Length
- 然后读取指定数量的字节以获取消息体
处理步骤:
- 读取起始行和所有头字段(直到空行)
- 检查Content-Length头字段
- 读取Content-Length指示的字节数
- 消息完成
缺少Content-Length: 如果消息体存在但缺少Content-Length:
- 在TCP上,连接必须关闭
- 这确保接收器知道消息何时结束
18.4 错误处理 (Error Handling)
传输层在传输消息时可能遇到各种错误。
客户端传输错误: 当客户端传输遇到错误时:
- 通知客户端事务传输错误
- 客户端事务根据第17.1.4节处理错误
- 通常会导致通知TU并终止事务
服务器传输错误: 当服务器传输遇到错误发送响应时:
- 通知服务器事务传输错误
- 服务器事务根据第17.2.4节处理错误
- 通常会导致事务终止
常见错误类型:
- 连接失败:无法建立TCP连接
- ICMP错误:目标不可达
- 超时:没有从网络收到响应
- TLS握手失败:无法建立安全连接
传输选择决策树
确定传输协议:
├─ 消息大小 > 1300字节?
│ └─ 是 → 使用TCP
├─ 消息大小 > (路径MTU - 200字节)?
│ └─ 是 → 使用TCP
├─ Request-URI或Route包含SIPS?
│ └─ 是 → 使用TLS
├─ Via头字段指示的传输?
│ └─ 使用指示的传输
└─ 默认 → 使用UDP
端口分配
| 传输协议 | 默认端口 | 用途 |
|---|---|---|
| UDP | 5060 | SIP标准端口 |
| TCP | 5060 | SIP标准端口 |
| SCTP | 5060 | SIP标准端口 |
| TLS | 5061 | 安全SIP端口 |
关键要点
- 强制实现:所有SIP元素必须实现UDP和TCP
- 消息大小:大消息(>1300字节或接近MTU)必须使用TCP
- 连接重用:建议重用连接以提高效率
- Via处理:sent-by字段用于路由响应
- 分帧:TCP需要使用Content-Length进行消息分帧
- 错误处理:传输错误通知事务层
- 多播限制:主要用于"单跳发现"场景
- NAT支持:rport参数支持NAT穿越
与其他层的交互
+-------------------+
| TU/Core | 应用逻辑
+-------------------+
↕
+-------------------+
| Transaction Layer | 事务状态机
+-------------------+
↕
+-------------------+
| Transport Layer | ← 本章描述
+-------------------+
↕
+-------------------+
| Network (UDP/TCP)| 底层网络
+-------------------+
本章小结:
第18章描述了SIP传输层的完整规范,包括客户端和服务器的传输行为。传输层是SIP协议栈中负责实际网络传输的基础层,处理UDP、TCP和TLS等不同传输协议。关键要点包括强制实现UDP和TCP、基于消息大小自动选择传输协议、连接管理和重用、Via头字段处理、以及面向流传输的消息分帧机制。理解传输层对于实现可靠且高效的SIP应用至关重要。