SIP 的地址不是 IP,是 URI——所以设备换 IP 只要重新注册,号码不变。 国标那 20 位编码不是流水号,它每一段都有含义,其中第 14 位错了最坑。
09.01.01 说了「注册把号码翻译成地址」,这一节讲号码本身。 07.02.01 讲 ONVIF 的 token 时说过「地址是设备告诉你的」, SIP 的 URI 是同一件事的另一套做法。
一、六种形状,一个语法
SIP URI 的通用形状是:
sip:用户@主机:端口;参数?头
五个部分只有「主机」是必需的,其余都可省:
| 部分 | 能不能省 | 省了会怎样 |
|---|---|---|
| 用户部分 | 能 | 只能用于 REGISTER |
| 主机 | 不能 | — |
| 端口 | 能 | 默认 5060 |
| 参数 | 能 | 用默认传输 |
第一行那个「只能用于 REGISTER」是硬规矩:sip:3402000000 这种地址没有用户部分,
它表示「这个域的注册服务器」,所以只能在注册时用。
对 INVITE 用这种地址会被拒——因为「呼叫一个域」没有意义,必须指明叫谁。
第三行那个默认端口 5060 是 SIP 的标准端口,和 RTSP 的 554、HTTP 的 80 一样属于「约定」。
二、五种元素
| 元素 | 干什么 | 能不能省 |
|---|---|---|
| UAC | 发起请求的一方 | 不能 |
| UAS | 接收请求的一方 | 不能 |
| 代理服务器 | 转发请求 | 能(点对点) |
| 注册服务器 | 登记号码与地址 | 大规模必需 |
| 重定向服务器 | 只回地址不转发 | 能 |
前两行是「角色」不是「设备」: 同一台摄像机在点播时是 UAS,在主动上传时又是 UAC——角色随「谁发请求」变,不随设备变。 第四行那个注册服务器是大规模系统的基础:没有它,主叫必须事先知道每台设备的 IP, 而 IP 会变(DHCP、换网段)。 国标平台就是「注册服务器 + 代理服务器」的组合:下级设备向它注册,上级平台向它请求转发。
三、20 位编码的结构
这一串数字不是流水号,它按位置分五段:
| 位 | 长度 | 含义 |
|---|---|---|
| 1~8 | 8 | 中心编码 |
| 9~10 | 2 | 行业编码 |
| 11~13 | 3 | 类型编码 |
| 14 | 1 | 网络标识 |
| 15~20 | 6 | 序号 |
第三行「类型编码」决定设备是什么: 132 是网络摄像机、131 是模拟摄像机加编码器、118 是报警输入。 国标附录有整张类型表,这一段的取值直接决定平台把它当「视频通道」还是「报警通道」。 所以「编码填错」的后果不是报错,而是「设备上线的类型不对」—— 平台照样能收到它,只是点播按钮是灰的。
四、第 14 位为什么最坑
这一位只有 0 和 1 两个值,含义却差很远:
| 值 | 含义 | 后果 | |---|---| | 0 | 走 SIP 域 | 正常注册 | | 1 | 走 ID 直连 | 注册能过、点播失败 |
第二行那种情况最难查:设备照样能注册成功、平台也能看到它在线, 但一点播就失败,而且失败原因往往只说「目标不可达」。 因为「ID 直连」模式要求平台知道设备的真实 IP, 而平台这边是按 SIP 域去找的——两边的寻址方式对不上。 排查办法很土但有效:把编码第 14 位改成 0 试一次,通了就说明是这个问题。 这一条是从现场案例里来的,规范里只写「网络标识」,不会告诉你「填 1 会这样」。
五、为什么用 URI 而不用 IP
这是 SIP 架构上最关键的一个选择:
| 用 IP | 用 URI |
|---|---|
| 换 IP 就要改所有配置 | 只需重新注册 |
| NAT 后面用不了 | 注册能穿透 |
| 一台设备只能有一个身份 | 可多号 |
第二行那个 NAT 穿透是实际原因之一: 内网设备注册到公网服务器时,服务器记下的是它看到的公网地址,设备自己不用知道。 第三行那个「可多号」也是有用的:一台编码器可以有好几个 SIP 号(对应不同通道), 用 IP 就表达不了这种关系。 代价是「多了一次翻译」: 每次呼叫都要先查号,多一跳延迟——这就是注册服务器存在的必要,也是它成为单点故障的原因。
六、动手 Demo:六种 URI 形状逐个解析
Demo 用一个正则把六种真实形状的 URI 拆开,看每个部分落在哪。 然后把 20 位编码按位切开。
uris = ["sip:34020000001320000001@3402000000",
"sip:34020000001320000001@3402000000:5060",
"sip:[email protected]:5060;transport=udp",
"sips:34020000001320000001@3402000000",
"sip:3402000000",
"sip:[email protected];user=phone"]
pat = re.compile(r"(sips?):([^@;]+)(?:@([^;:]+))?(?::(\d+))?(.*)$")
for x in uris:
sch, u1, host, port, rest = pat.match(x).groups()
if host is None:
u1, host = None, u1
print(sch, u1 or "-", host, port or "-", rest or "-")
code = "34020000001320000001"
print(code[0:8], code[8:10], code[10:13], code[13], code[14:])
实跑输出:
--------------------------------------------------------------------
六种 URI 形状逐个解析
--------------------------------------------------------------------
**SIP 的地址就是 URI,但它比 HTTP 的 URL 花哨得多**:
方案 用户部分 主机 端口 参数
---------------------------------------------------------------------------
sip 34020000001320000001 3402000000 — —
sip 34020000001320000001 3402000000 5060 —
sip 34020000001320000001 192.168.1.64 5060 ;transport=udp
sips 34020000001320000001 3402000000 — —
sip — 3402000000 — —
sip alice example.com — ;user=phone
**六行覆盖了所有形状**:**带不带用户、带不带端口、带不带参数。**
**第一行与第二行是同一个地址**——**5060 是默认端口,写不写等价。**
**第四行的 `sips` 是「强制 TLS」**,
**GB/T 28181 的早期版本用过,现在的项目基本还是 `sip` + UDP。**
**第五行那种「只有域名」的写法专门给 REGISTER**,
**因为注册的 Request-URI 只写域**(下一个 Demo 会看到)。
**20 位编码不是随便凑的,它有结构**:
位 本例 含义
------------------------------------
1~8 34020000 中心编码
9~10 00 行业编码
11~13 132 **类型编码**
14 0 网络标识
15~20 000001 序号
**第三行「132」表示网络摄像机(IPC)**,
**「131」是模拟摄像机加编码器、「118」是报警输入**——
**这套编码在 GB/T 28181 里叫「设备类型」,国标附录有整张表。**
**第 14 位那个「0」是网络标识位**,
**0 表示走 SIP 域、1 表示走 ID 直连**——**这一位错了,注册能过、但点播失败。**
输出第一行的 sip:34020000001320000001@3402000000 拆成:
方案 sip、用户 34020000001320000001、主机 3402000000。端口和参数都是 —,因为用的默认值。
第五行那个 sip:3402000000 用户部分是 —,只有主机——这正是 REGISTER 用的形状。
正则里那个「用户部分不能含 @ 和 ;」是关键,因为 @ 分隔用户与主机、; 开始参数;
而「主机不能含 ; 和 :」是因为冒号后面是端口。
代码里那个 if host is None 是个补丁:没有用户部分时,正则会把它当成主机匹配掉,
所以要交换一下。
这种「一个正则处理两种形状」的写法很常见,但也容易出错——
生产代码里最好分两条正则,别省这几行。
最后一行输出的五段就是编码结构:34020000 00 132 0 000001。
30 秒实验
- 把编码第 14 位从 0 改成 1,看解析结果哪一段变了。
- 给 URI 加一个
?subject=xxx,看参数和头的分界在哪。 - 用
sip:3402000000发一条 INVITE,看 UAS 回什么码。
常见误区
- 以为 SIP 地址里必须带用户部分。 REGISTER 的地址就只有域, 而且对 INVITE 用这种地址会被拒。
- 以为 20 位编码的后六位才是唯一标识。 前面几段决定「它是什么」,类型编码填错, 设备上线类型就不对。
- 以为第 14 位填什么都一样。 填 1 走 ID 直连,注册能过但点播必失败, 而报错只说「目标不可达」。
自测三问(点开对答案)
1. 为什么 `sip:3402000000` 只能用于 REGISTER? —— **它没有用户部分,表示「这个域的服务器」**。 呼叫必须指明叫谁,所以对 INVITE 用这种地址会被拒。 2. 20 位编码的哪一段决定「平台把它当什么设备」? —— **第 11~13 位的类型编码。** 132 是网络摄像机、131 是模拟加编码器、118 是报警输入, 取错则平台按错误类型收录。 3. 用 URI 而不用 IP 的代价是什么? —— **多一次号码到地址的翻译**,即多一跳延迟,而且注册服务器成了单点故障。下一节讲三元组——SIP 靠三样东西把一堆报文认成一次会话。
- ☐ (本节完,下一节 09.01.04 SIP会话构成)