通讯层负责请求和应答在网络上的实际传输。这包括了在面向连接的通讯方式下的请求和应答所使用的连接管理。

通讯层负责管理像TCP/SCTP之类通讯协议的长连接,或者在这些协议上的TLS连接,并且包括管理打开这些连接的使用者的管理。这包括了客户端或者服务端,通讯层打开的连接,这样在客户端和服务端通讯函数可以共享这些连接。这些连接采用一组用远端的地址,端口,通讯协议标志的索引来进行管理。当通讯层打开了一个连接,这个连接的索引就设置成为远端的IP和端口,还有打开这个连接的通讯层的实例。当通讯层接收了一个连接,那么这个连接的索引就被设置成为连接方的源IP地址和port,还有通讯层的实例transport。注意,由于源端口port通常是临时创建的,所以通讯层被动接收的连接通常是不被重复使用的。这就是说,如果两个proxy再一个“peering”(点对点)的关系中,使用一个面向连接的通讯协议通常有两个连接要使用,每个都是自己作为主动方连接的。

我们建议在实现中,当发送(或者接收)完成最后一个消息之后,依旧维持这个连接一段时间(这段时间可以是实现自己定义的时间)。这段时间应当是至少等于本节点的事务从创建到结束的最长时间。这是为了让事务能够在他们所创建的同一个连接上完成(比如,在这个连接上完成请求,应答的处理,在INVITE的情况下的给非2xx的ACK应答等等)。这通常意味着至少64×T1秒。不过,如果当本程序的TU使用的是一个比较大的定时器C的时候,也可以选取一个比较大的值。

所有的SIP元素都必须实现基于UDP和TCP的通讯。SIP元素还可以实现其他的协议。

要求UA支持TCP是对RFC2543的一个重要改进。这是由于需要处理更大的消息,就像接下来讲到的那样,必须使用到TCP协议。因此,即使是SIP元素不要发送大的消息,但是由于它可能收到大消息并且处理这些消息,所以,要求支持TCP。

1. 客户Clients

1.1. 发送请求

通讯层的客户端负责发送请求和接收应答。通讯层的用户把请求交给通讯层的实例进行处理,包括IP地址端口,通讯层实例,还有可能有多点广播的TTL。

如果请求的大小和MTU差是在200个字节以内的,或者它是大于1300字节的,并且路径MTU的大小是未知的,那么请求必须遵循RFC2914控制阻塞的传输协议,比如使用TCP。如果这导致了Via最上边指定的通讯协议的改变,那么Via最上边的值就必须也随之改变。这使得在UDP传输上的消息的分割,并且也提供了大消息的传输阻塞控制。不过,在实现上,必须能够支持达到最大包,大小的消息的处理。对于UDP来说,包含了IP和UDP头的大小是65535个字节。

在消息的大小和MTU之间的200个字节的“buffer”,提供了一个机制使得在SIP的应答中,可以超过请求的大小。比如在INVITE请求的应答中,增加了Record-Route头域值。有了这个额外的buffer,应答可以大概比请求大170个字节,而且在Ipv4上不用进行分块传输(假设没有IPSec,大概IP/UDP会使用30个字节)。当MTU是未知的时候,选取1300是基于假设Ethernet的MTU是1500字节的基础上。

如果SIP元素是因为消息大小的限制,所以基于TCP发送一个请求,并且消息如果不是因为大小的限制,会使用UDP来发送,并且如果建立连接产生一个ICMP 协议不支持的错误,或者导致TCP reset,那么这个元素就应当用UDP重试这个请求。这只是为了向后兼容RFC 2543针对不支持TCP的实现。在本规范以后的改动中,这部分内容会有修订。

如果客户端向多个地址发送请求,那么必须增加“maddr”参数到Via头域值上,并且这个参数值指定多个目的地址,对于Ipv4来说,应当增加“ttl”参数=1,IPV6的多点传送在本规范中没有定义,会在后续的标准中描述。

这些规则定义了SIP的多点传送。首要的目的是为了提供“寻找最接近的单点”服务(“single-hop-discovery-like”),这个服务将请求转发到一组类似的服务器,并且只需要处理其中任意一个服务器的应答。这个功能主要用于注册服务。实际上,基于上节的事务处理规则,客户端事务会接收第一个应答,并且因为其他应答包含同样的Via的branch参数,而视这些应答为重发应答。

在请求发送,客户端通讯层必须在Via头域中增加一个“sent-by”栏。这个字段包含了一个IP地址或者主机名,端口。我们推荐使用FQDN方法描述这个主机名。这个字段在某些特定情况下,用于发送应答。如果端口不存在,缺省的值依赖于通讯协议。对于UDP,TCP和SCTP来说是5060,TLS是5061。

对于可靠传输协议,应答通常简单的通过连接发送,并且这个连接是收到对应请求的连接。因此,客户端传输层必须准备在发出请求的同一个连接上接收应答。在出现错误的情况下,服务端可能会尝试新建立一个连接来发送应答。为了能够处理这种情况,通讯层必须准备接收一个从源IP建立的新连接,这个连接的IP是请求发起的源IP,port是在“sent-by”字段中指定的port。

对于非可靠的传输协议,客户端通讯层必须准备从发送请求的那个原始IP地址上接收应答。(因为应答会送到原始地址去),并且端口号是在“sent-by”字段的端口好。进一步说,和可靠传输一样,某些情况下,应答会发往不同的地方。客户端必须能够准备从其他地址和端口上接收应答。

对于多点传送的情况来说,客户端通讯层必须准备从相同的多点传输组,上接收应答,这个组的地址和端口和发出请求的组相同(就是说,它必须是发送请求的那个多点传输组,的一个成员)。

如果请求发送的目的IP地址,端口和transport都和现有的一个连接相同,那么建议使用这个连接来发送请求,同时也允许新建立一个连接来发送。

如果请求通过多点发送,那么它发送的一组地址,端口和TTL都是由通讯层的用户提供。如果请求是通过不可靠通讯协议发送,那么发送的IP地址和端口也是由通讯层的用户提供。

1.2. 接收应答

当应答接收到的时候,客户端通讯层检查最上的Via头域值。如果“sent-by”参数不符合客户端通讯层在请求中插入的值,那么这个应答必须悄悄丢弃。

如果由任何客户端事务存在,客户端通讯层使用上节的步骤来匹配现存的事务和这个接收到的应答。如果匹配到了,应答必须交给事务层进行处理。否则,应答必须交给核心去处理(无论是有状态的proxy,还是无状态的proxy,还是UA的核心)。处理这些“stray”(迷路)的应答是基于核心的策略的(如果是proxy就会转发,如果是UA就会忽略,等等)。

2. 服务端

2.1. 接收请求

一个服务器应当能够接收从任何IP地址、端口和协议上过来的请求。他们是通过对这个服务器的SIP或者SIPS URI的DNS查找,得到这个服务器的地址然后连接和发送的请求的。在这里,“handing out”(发布)包含了在REGISTER请求或者转发应答的Contact头域中放一个URI,或者在请求或者应答的“Record-Route”头域中放一个URI。这个URI可以通过放在网页或者名片上被“handing out”(发布)。同样的我们也建议服务器在公网上监听缺省的SIP端口(TCP/UDP是5060,5061是在TCP上的TLS)。如果是在局域网上,或者私有网上,或者一个物理服务器上运行好几个服务实例,那就很自然的可以设置成不同的。对于服务器监听UDP的任何端口和界面,都必须在TCP上也进行同样的监听。这是因为可能消息还需要通过TCP进行传输,比如消息过大的情况。所以,在相反的情况下就不需要了。如果一个服务器在TCP监听了,那么它不一定需要在UDP上也进行相应的监听。当然服务器也可以因为某些原因在特定地址和端口上监听UDP。当服务端事务从任意一个通讯层上接收到一个请求的时候,它必须检查最上的Via头域的“sent-by”参数。如果“sent-by”参数的主机部分包含了一个主机名,或者它包含的IP地址和包的源地址不同,服务器必须增加一个“received”参数到这个Via头域值中。这个参数必须包含收到的包的原地址。由于服务端必须把应答发送给收到请求的那个源IP地址,所以这个可以用来帮助服务端通讯层发送应答。

一个服务端通讯层收到的请求可能是这样的(部分):

INVITE sip:bob@Biloxi.com SIP/2.0

Via: SIP/2.0/UDP bobspc.biloxi.com:5060

请求是从源IP:192.0.2.4收到的。在请求转交到上层之前,通讯层增加了一个“received”参数,这样请求的部分就是:

INVITE sip:bob@Biloxi.com SIP/2.0

Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4

接着,服务端通讯层尝试和服务端事务做匹配。这个使用的是上节定义的规则。如果匹配上一个服务端事务,那么请求就交给那个事务去处理。如果没有匹配到事务,请求就交给核心去处理,可能会创建一个新的服务端事务来处理。注意当UAS核心给INVITE请求发送一个2xx应答的时候,服务端事务已经销毁了。这就是说,当ACK收到的时候,不会有匹配的服务端事务,并且基于这个规则,ACK回交给UAS核心来处理。

2.2. 发送应答

服务端事务使用最上边的Via头域值来决定把应答发送到哪里。它必须遵从如下步骤来发送:

Ø  如果“sent-protocol”是一个可靠的传输协议比如TCP或者SCTP,或者在其上的TLS,应答必须用现存的到原始请求(创建这个事务的请求)的连接进行发送(如果连接还存在的情况下)。这个要求服务端通讯层保留服务端事务和通讯层连接的相关性。如果连接不存在了,服务端应当创建一个新的连接,如果存在“received”参数,就用对应的在“received”参数中指定的IP地址。如果存在“sent-by”参数,那么就用“sent-by”指定的port,如果不存在,那么就用缺省的port。如果对应的连接已经失效,那么服务器应当采用附件的步骤来决定使用那个IP地址和端口来建立连接并且发送应答。

Ø  否则,如果Via头域包含一个“maddr”参数,就必须把应答转发到maddr所指明的地址,并且使用“sent-by”所指定的端口,如果没有sent-by参数,那么就使用5060缺省参数。如果地址是一个多点地址,应答应当使用“ttl”参数所指定的TTL,或者如果没有指定“ttl”参数,则使用TTL=1的参数。

Ø  否则(对于非可靠传输),如果Via的最上头域包含一个“received”参数,那么应答必须发送到“received”参数所指定的地址,并且使用“sent-by”所指定的端口,如果没有sent-by参数,那么就使用5060缺省参数。如果这步失败了,比如,如果得到一个ICMP端口不能到达的错误,那么就应当根据附件的第5节的步骤来决定应当把应答发送到哪里。

Ø  否则,如果没有receiver-标记,那么应答应当使用附件的第5节指定的步骤,送到“sent-by”参数指定的地址。

3. 分块

在面向消息的通讯协议中(比如UDP),如果消息有一个Content-Length头域,那么消息体就有可能包含很多字节。并且收到的包中除了这个消息体的Content-Length字节意外,还有通讯层附加的通讯包字节,那么这部分额外的字节应当被丢弃。如果通讯包在没有收到完整的Content-Length字节的消息体就终止了,这就意味着出错了。如果这个消息是一个应答,那么这个消息必须被丢弃。如果消息是一个请求,那么本程序应当给出一个400(Bad Request)应答。如果消息没有包含一个Content-Length头域,消息体的结束点就是消息体的结束点。

在面向流的通讯协议中(比如TCP),Content-Length头域标志这包体的大小。在面向流的通讯协议中,必须使用Content-Length字段。

4. 错误处理

错误的处理取决于出现错误的消息是请求还是应答。

如果通讯层的用户要求在一个非可靠传输协议上发送一个消息,并且结果是一个ICMP错误,那么错误处理的方法依赖于ICMP错误类型。当通讯层遇到主机、网络、端口或者协议无法到达的错误,或者参数错误的时候,应当通知通讯层的用户发送失败。Source quench和TTL exceeded ICMP错误应当被忽略。

如果通讯层用户要求在一个可靠传输协议上发送一个请求,并且结果是一个连接错误,通讯层应当通知通讯层用户这个发送错误

通讯(transport)相关推荐

  1. dubbo源码解析(九)远程通信——Transport层

    远程通讯--Transport层 目标:介绍Transport层的相关设计和逻辑.介绍dubbo-remoting-api中的transport包内的源码解析. 前言 先预警一下,该文篇幅会很长,做好 ...

  2. Elasticsearch基础整理 脑图

    Elasticsearch知识整理,基于ES6.7.1 主要涉及ES集群各模块功能及使用说明,集群选举流程 读取/写入流程等等,不涉及dsl等具体操作,后面会持续更新! 需要完整文件 到我 公众号 ' ...

  3. ntrip获取源列表_Ntrip通讯协议怎么样?

    1 什么是Ntrip? CORS(Continuously Operating Reference Stations)就是网络基准站,通过网络收发GPS差分数据.用户访问CORS后,不用单独架设GPS ...

  4. 一些通讯知识、TCP/IP、三次握手四次分手(正确的图,网上很多错了)、HTTP\HTTPS、DNS、UDP

    总述 这里会按照一个浏览器(客户端)是向服务器请求资源的路径来分享知识点 有些内容在之前的博客有,您可以自取 浏览器(客户端)是如何向服务器请求资源的呢? 见下图: 客户端输入网址(输入搜索内容也是一 ...

  5. 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯...

    在一个基于面向服务的分布式环境中,借助一个标准的.平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互.这个交互的过程实 ...

  6. 网络编程2_网络通讯协议, socket(tcp, udp)

    一. 网络通讯协议     互联网协议的功能: 定义计算机如何接入internet, 以及接入internet的计算机的通信标准     互联网协议按照功能的不同分为osi七层或tcp/ip五层    ...

  7. 西门子S7以太网通讯协议

    S7以太网协议属于TCP/IP协议族的一种,下图为S7以太网协议在ISO-OSI参考模型中的位置. 通过WireShark抓包,可以看出S7以太网协议的模型: ISO-OSI参考模型.TCP/IP模型 ...

  8. WCF与现行分布式通讯技术性能对比

    1:前言 WCF是FrameWork3.0下的分布式框架. 本文讨论WCF与现行分布式通讯框架的性能对比.要求阅读者有一定的WCF基础(可以参照Windows Communication Founda ...

  9. boost asio 异步实现tcp通讯

    一.前言 boost asio可算是一个简单易用,功能又强大可跨平台的C++通讯库,效率也表现的不错,linux环境是epoll实现的,而windows环境是iocp实现的.而tcp通讯是项目当中经常 ...

  10. 【学习笔记】HTTP通讯基础

    HTTP通讯基础 一.HTTP 协议用于客户端和服务器端之间的通信 起始行开头的"GET"表示请求访问服务器的类型,称为方法(method). 随后的字符串 /index.htm ...

最新文章

  1. C# 代码注释规范文档
  2. C语言-宏定义#define的用法
  3. 如何在cmd运行python文件夹_python怎么在cmd运行文件夹
  4. NYOJ 643 发短信
  5. HTML5 Web SQL
  6. 视频容器格式与编码格式简介
  7. 机器阅读理解中文章和问题的深度学习表示方法
  8. python内核死亡的原因_Python的内核由于DLL而死亡
  9. 计算机网络之数据链路层:12、CSMA/CA协议-随机访问介质访问控制
  10. iOS - UIControl
  11. 查看linux用户编码,linux查看服务器编码
  12. matlab多元函数拟合,只有数据,不知道函数形式,未知函数关系的多元函数拟合
  13. P1095 [NOIP2007 普及组] 守望者的逃离
  14. MySQL之——mysqldump参数详细说明
  15. Nginx的启动、停止与重启
  16. C20_OC10-内存管理
  17. android高仿京东秒杀,Android实现京东秒杀界面
  18. win7下ODBC数据源ACCESS2003的链接
  19. 电能管理系统在惠氏公司的应用
  20. 系统错误:下列引导或系统启动驱动程序无法加载: HWiNFO32

热门文章

  1. 【语言处理与Python】1.3计算语言:简单的统计
  2. Android Contacts(二)—— SMS 短信 与 Contacts 联系人关联
  3. 为ASP.NET封装的SQL数据库访问类(转)
  4. [转]SQL SERVER数据库开发之触发器的应用
  5. A Deep Learning Tutorial: From Perceptrons to Deep Networks
  6. [1-7] 把时间当做朋友(李笑来)Chapter 7 【从此时此刻开始改变】 摘录
  7. ubuntu16.xxx安装mysql5.0项目迁移环境搭建
  8. Selenium WebDriver控制操作(Python)
  9. 转 web 开发字体
  10. Way back into love