写 SIP 服务后台前,先把 SIP 和 PSTN 搞清楚

张开发
2026/5/31 6:26:32 15 分钟阅读
写 SIP 服务后台前,先把 SIP 和 PSTN 搞清楚
文章目录1. 写在最前面2. 为什么 SIP 和 PSTN 很容易被搞混3. 先看两通最普通的电话3.1 第一通1001 打 10023.2 第二通1001 打 138xxxx88884. SIP 到底在这两通电话里管什么5. 为什么会出现「接通了但没声音」6. 那些总是冒出来的词到底该怎么记7. 写 SIP 后台时真正难的到底是什么8. 如果我是写后台的人我到底该先盯住什么9. 碎碎念10. 参考资料1. 写在最前面最近准备去写一个和SIP相关的后台服务。最开始笔者以为这件事的重点应该是先把协议文档看懂把REGISTER、INVITE、BYE这些流程背下来。结果真正开始查资料之后发现自己最先卡住的反而不是某个字段而是几个更基础的问题SIP到底是不是「打电话」本身PSTN到底是什么为什么有时候电话明明接通了却没有声音为什么分机互打和打手机号系统里出现的东西完全不一样如果这些问题没想清楚后面越看资料越容易乱。因为脑子里会一直把很多东西糊成一团最后只剩下一个很模糊的印象反正都是打电话相关的东西。但真到要写后台的时候这种模糊理解基本不够用。因为你很快就会碰到这种很实际的问题这通电话到底是建立失败了还是声音没传过去分机号和手机号为什么不能按同一套逻辑处理日志里到底该看什么才能把一通电话串起来所以这篇文章不打算上来就讲协议而是想先把问题拆清楚。对现在的笔者来说真正重要的不是先把术语背熟而是先知道一通电话到底可以从哪几个层面去看。2. 为什么 SIP 和 PSTN 很容易被搞混现在回头看笔者觉得自己一开始会被绕晕其实是因为平时说「打一通电话」时默认把很多事情都当成了一个动作。但如果站在后台视角去看这件事至少可以拆成三层这通电话怎么建立起来声音怎么传过去如果目标是手机号这通电话最后要落到哪里一旦不先拆开后面就很容易把下面这些东西混在一起SIPRTPPSTN外部中继网关所以现在如果让我先给自己留一个最小理解我会先这么记SIP 管的是「这通电话怎么建立」 RTP 管的是「声音怎么传」 PSTN 是「真实电话号码所在的电话网络」这句话并不够完整但已经足够把很多混乱先压下来了。3. 先看两通最普通的电话如果不先看具体场景后面的概念很容易飘。所以笔者现在更愿意只看两通最普通的电话。3.1 第一通1001打1002假设这是两个内部分机。那这通电话先不用带太多术语去看可以先理解成这样1. 1001 先告诉服务端「我在线」 2. 1001 发起呼叫目标是 1002 3. 1002 开始响铃 4. 1002 接听 5. 双方开始说话 6. 某一方挂断这个场景里笔者觉得最值得先记住的不是报文名而是两个问题这通电话现在建立到哪一步了声音现在有没有正常传起来因为你后面看到的REGISTER、INVITE、200 OK、BYE本质上都只是在描述第一件事这通电话走到哪一步了。也就是说在这个场景里系统主要还是在处理一条内部呼叫链路。3.2 第二通1001打138xxxx8888如果1001打的不是1002而是一个普通手机号那事情就不一样了。因为这时候这通电话不能只在系统内部打转它最后一定要落到真实电话号码那边去。链路大概会变成这样1001 - 你的 SIP 服务 - 外部语音出口 - PSTN - 手机用户到这里PSTN这个词才真正有了位置。它不是一个和SIP并排的协议名而是电话最后要去到的那张网。所以如果要把这两通电话的差别说得再直白一点那大概就是分机互打更多是在系统内部把一通呼叫接起来打手机号除了内部呼叫控制还多了一段「把电话送进真实电话网络」的过程这一步一旦想清楚后面为什么会出现外部中继、网关、运营商线路其实就没那么难理解了。4. SIP 到底在这两通电话里管什么写到这里再回头看SIP就会比一上来背定义更清楚一点。SIP最核心的作用并不是「替你把声音传过去」而是负责让一通电话从开始到结束有状态可跟。更直白一点说它管的是这些事谁要呼叫谁对方是不是在响铃对方有没有接起来这通电话是不是已经挂断所以对写后台的人来说SIP最重要的价值不是它有多像协议而是它能把一通电话的状态组织起来。这也是为什么我现在越来越觉得SIP后台更像一个呼叫状态机而不只是一个「收发报文的服务」。因为你真正要维护的往往不是某一条消息而是谁已经注册谁正在呼叫谁这通电话处于振铃、接通还是已经结束失败到底发生在什么阶段如果从工程视角去看这一层其实就是后面业务控制的基础。5. 为什么会出现「接通了但没声音」这个问题笔者一开始是真的很疑惑。既然电话都接通了为什么还会没声音后来才慢慢意识到原来「把电话接起来」和「把声音传过去」不是一回事。在前面的两个例子里其实一直都藏着两条线一条线是呼叫有没有建立起来一条线是声音有没有真的传起来前一条更多和SIP有关。后一条通常更多和RTP、媒体地址、网络连通性这些事情有关。所以才会有一种特别经典的现象看起来已经接通了双方都进入了通话状态但就是听不到声音这时候往往不是呼叫建立失败了而是媒体那条链路出了问题。比如地址给错了内网地址跑到了公网NAT 没打通媒体没有经过该经过的节点所以对写后台来说一个特别重要的认知是「接通」和「有声音」其实是两件事。这个点如果一开始没分清后面排查问题时会非常容易误判。6. 那些总是冒出来的词到底该怎么记当开始看资料以后很快就会遇到这些词SBCGatewaySIP Trunk一开始真的很容易看烦。因为每多一个词脑子里都像是又多了一个要背的概念。但后面笔者发现刚开始其实不用把它们记得太学术先把它们放回上面第二通电话里去看就够用了。如果1001要打手机号那系统中间往往会多出一些「负责出网」的角色。我现在更愿意这么理解SIP Trunk系统往外打电话时用的语音出口Gateway负责把系统这一侧接到传统电话网络SBC更像边界上的守门员处理公网接入、安全、NAT 这些问题只要把这些角色放回「1001打手机号」那条链路里基本就不会再觉得它们是凭空冒出来的词了。7. 写 SIP 后台时真正难的到底是什么写到这里笔者反而越来越觉得写SIP后台时最重要的不是上来就背一堆术语而是先盯住几个最实际的问题谁注册上来了这通呼叫现在在哪个阶段分机号和手机号要怎么分开走外呼的时候该走哪个出口出问题时是呼叫建立的问题还是声音传输的问题继续往下想会发现真正难的地方通常也不在于「把一条INVITE发出去」。真正难的往往是内线和外线怎么区分不同号码该走哪条出口某个出口失败后要不要切别的挂断、拒接、超时这些状态怎么统一表达也就是说真正难的地方很多时候不是协议本身而是路由怎么做状态怎么管问题怎么定位一旦开始从这个角度看SIP后台就会越来越像一个呼叫控制系统。8. 如果我是写后台的人我到底该先盯住什么写到这里笔者会更愿意把注意力收回到开发本身。如果后面真的开始写后台那我最先会逼自己想清楚的其实是下面几件事注册信息怎么维护呼叫状态怎么表示内线和外线怎么区分打手机号时走哪个出口一通电话的日志怎么串起来最后这一点尤其重要。因为一通电话看着只是用户点了一下拨号但到了后台里往往会跨很多节点。这时候如果没有一个稳定的标识后面排查起来会非常痛苦。所以后面你大概率会在日志里反复看到Call-ID这个字段。可以先把它粗暴理解成「这通电话自己的 id」。先知道这一点后面串日志时会省很多劲。所以现在回头看写SIP后台真正要做的其实不是把所有术语都背全而是先把下面这几层分开看呼叫有没有建立起来声音有没有真的传起来这通电话有没有走到真实电话网络边界一旦清楚后面很多设计和排查思路都会顺很多。9. 碎碎念写这篇之前笔者其实最怕的是把自己也绕进去。因为SIP、RTP、PSTN这些词一旦一起出现就很容易越看越像一团。但现在至少有一件事是清楚的了先不要一上来就背协议先把「呼叫建立」「声音传输」「电话落网」这三件事分开看。分开以后很多概念自然就有位置了。后面如果真的开始写后台笔者会先把问题看清楚再去补术语而不是反过来。不能等到清晰了以后再去做不去做就永远清晰不了在做的过程中才会逐渐清晰起来的。我们不会长生不老我越想到这个越觉得不能浪费人生。因为生命仅此一次任何事情无论它是有趣的好笑的或是重要的都仅此一次。你知道的每天都有可能是我们的最后一天。10. 参考资料RFC 3261SIP: Session Initiation ProtocolRFC 3550RTP: A Transport Protocol for Real-Time ApplicationsRFC 4566SDP: Session Description ProtocolITU-T E.164国际公用电信编号计划

更多文章