很多年前,我们刚刚接触互联网。一天,老师上完课之后就在黑板上写了一个如下的东西让大家去下载资料。
 
URL Http://www.abc.edu.cn/abc
 
我们觉得很好笑,为什么老师要加个URL呢,我们已经都知道这不就是一个互联网地址了罢了,那个URL是什么意思,后来虽然知道了URL 的全称是Uniform Resource Locator,翻译为统一资源定位器,但是更深层次的东西就一直不得其解了。
后来随着知识慢慢地增加,我开始理解这个URL的意义:准确的定位资源。好比在茫茫资源中,我可以按照一个标记来找到我要的资源。那么为了标记一个资源,我们就要用Uniform Resource Identifier (URI)来进行标识。
 
我们今天的话题就从这个唯一资源标示符-URI开始,配置过的OCS的可能都知道,我们在为用户启用了企业语音之后,都要为用户填入一个Line URI,而且格式必须是tel:开头的。大家或许也就填了一个,但是没有去想过为什么要这么填。
正如电视剧《LOST》里面说的Everything happen for a reason。每件事都是有原因的。微软为什么要这么让大家填入也是有原因的。根本原因是要在茫茫的诸多电话号码中定位我们的这个用户,我们必须参照IETF规范的RFC 2806(需要注意RFC 2806现在已经被RFC 3966所代替)。而RFC 2806里面则定义了资源的URI格式要使用“tel:”这样的格式。“tel:”仅仅代表了telephone-uri,除此之外还有 extension,context等我们常见的几种语法。
比如说extension的格式为:“;ext=”,而context的格式为:“;phone-context=”。知道了这这两点之后那么我们如果看到这样的Line URI也就不会觉得奇怪了:
tel:+12345
tel:+12345;ext=123
tel:+12345;phone-context=dialstring@lyncpbx.net
他们都是资源的定位符。其中phone-context 定义了这个tel url在什么范围内是有效的。
 
如果大家有配置过Exchange和OCS的集成的话,在你为用户启用了UM之后,用户的地址那里会多出一个EUM,然后格式为123;phone-context=umdialplan这样的字符串,我想现在你也应该明白了它的来历了吧,至于这些字符的意思,我们接着来分析。
 
如果仅仅给你几个单独的数字,你绝对不会知道他的意思。比如说我们+861012345678,假设我要说这个是我们电话世界里面的某一个电话机的号码,那么你就可能会猜到,这是北京的号码。因为大家知道,中国的代码是+86,而北京的区号是010。那么定义这些代码的规矩就成为Number Plan,翻译为号码规范。全球最著名的号码规范就是E.164了。E.164 的全称是international public telecommunications numbering plan。它是由国际电信联盟在1997年发布的。这个规范建立了全球号码的框架,并且了每一个国家分配了国际代码,中国的就是+86。当然为了方便和一些特殊的原因,国内在地区码被认为的在前面加了一个0,这个0在我们号码的标准格式下是不存在的。
 
E.164有一些特点:
  • 一个号码最大只能有15位;
  • 号码的第一部分为国际代码country code(CC);
  • 号码的第二部分为区域代码national destination code (NDC);
  • 第三部分为接入代码subscriber number (SN);
  • NDC和SC合起来称为可以成为标识码
当一个北京的用户向电信申请了一个座机号码01012345678,当用户把这个电话接入电话网的时候,号码就有了E.164这个号码规范,他的号码前会加一个86,这样国外的用户就可以定位到这个用户。因为它的号码变成了+861012345678。需要注意的是这串号码中,只有+86来自于E.164,,其它部分都不是。那么为什么国内的用户不加+86可以拨通这个号码呢,因为这个号码和一个叫做Dial Plan(拨号计划)的概念联系在了一起。每一个号码都要和一个拨号计划关联起来,因为拨号计划制定了一个用户在话机上怎么拨号码以便接通号码。比如说同在北京的用户不要加010就可以接通这个号码,而外地的用户就需要加010才可以接通到这个号码。这些就是拨号计划所制定的了。
 
不要搞混淆了,号码规范是定义了号码怎么分配,拨号计划制定了一个用户在话机上怎么拨号码以便接通号码。
 
如果大家对SIP熟悉的话,那么我们知道一般的sip设备都和一个拨号计划联系在了一起,因为一是可以实现用户拨打完号码就可以拨出去,而不需要在去按一下dial键,二是用户输入的可以按照给定的拨号规则来进行转换。
如果我们在一个隶属于lyncpbx.net域的SIP设备上拨打了12345678,那么sip设备在经过拨号计划就会把号码转变为+86102345678 ,所以设备所发出了请求就会为:
INVITE tel:+86102345678 SIP/2.0
但是为了让SIP URI成为一个规范的SIP URI,user=phone字段会被插入到语句中。所以最终发出的请求就为:
INVITE sip:+861012345678@lyncpbx.net;user=phone SIP/2.0
 
如果用户发出的是INVITE sip:12345678;phone-context=dialstring@lyncpbx.net;user=phone SIP/2.0,通过上面的分析,大家也应该知道是什么意思了吧。