Sofia-SIP辅助文档十四 - Sofia SIP用户代理库 - "tport" - 传输模块

http://sofia-sip.sourceforge.net/refdocs/tport/index.html翻译自官网的这张网页。


模块信息

tport模块提供可供SIP、RTSP和HTTP使用的通用的传输接口。这是一个抽象层,介于协议栈和传输协议实现之间。接口通过传输对象来实现。传输对象的tag参数在<sofia-sip/tport_tag.h>头文件中被定义。

联系人:
Pekka.Pessi@nokia-email.address.hidden
状态:
Sofia SIP Core library
许可:
LGPL

Master, Primary and Secondary传输对象

一个传输对象可以以三种角色被使用。Master传输对象表示所有可能的传输。它被用来保存stack和root接口,以及类似于SigComp状态处理器的通用数据。primary传输对象表示可用的传输。secondary传输对象表示实际的传输连接。

一个协议栈首先创建一个master传输对象,然后绑定许多的primary传输对象(每个代表一个传输协议,例如UDP、TCP、TLS/TCP和SCTP等等)。绑定过程为每个支持的传输协议创建一个新的primary传输对象。如果协议栈作为一个服务端使用,邦定过程还将创建必要的服务器sockets,并且将它们绑定到指定的服务器端口上。

secondary传输对象为每个传输层连接创建。tport模块负责自动创建它们,当它们不再被使用时自动销毁它们。当一个面向连接的传输协议被使用时,secondary传输对象被要求用来传输消息。

一个secondary传输对象因为两个理由而被创建。一个服务器可以接收来自客户端的新的连接,或者一个客户端可以连接服务器。当属于一个secondary传输对象的连接建立完毕后,协议栈可以通过发送和接收消息。

初始化传输

当用tport_tcreate()函数创建了一个primary传输对象时,协议栈必须传递一个包含函数指针的tport_stack_class_t结构体给这个传输对象。这些函数指针用来

  1. 创建用来存放接收到的消息的消息对象
  2. 传递接收到的消息给一些栈
  3. 报告错误给协议栈

函数tport_tbind()用来将传输协议绑定到primary传输对象。协议栈给出期望的服务器传输名称(传输名称是个包含文本格式的socket地址和传输名称的结构体)以及栈支持的传输协议列表。tport_tbind()函数可多次调用,例如,传输协议的服务器端口可不同(例如,缺省SIP的TCP端口是5060,缺省SIP的TLS端口是5061)。

面向连接的和无连接传输

secondary传输对象为每一个传输级别连接创建。tport模块负责自动创建它们,当它们不再被使用时自动销毁它们。当面向连接的传输协议使用时secondary传输对象要求用来发送数据。

secondary传输对象由于两个原因被创建。一个服务器可能接收一个新的从客户端的连接,或者一个客户端连接到服务器。当属于secondary传输对象的连接建立好后,协议栈可以通过它发送和接收消息。

面向连接的和无连接传输

一个传输可以是面向连接的(TCP,SCTP)或无连接的(UDP)。一个面向连接的传输需要在消息发送前建立起连接。它可以只发送消息给单一地址。对无连接传输而言,一个目标地址必须给出。

一个无连接传输可以给多个地址发送消息。无论何时一个消息通过无连接传输发送目标地址必须提供。

注意如果tport_set_params()函数被调用时使用了TPTAG_CONNECT(1)参数,UDP可以使用面向连接的方式(客户端不使用sendto(),而是connect()然后send())。

流和数据报传输

一个面向连接的传输既可以用于基于流的协议(TCP,SCTP)也可以用于基于包的协议(UDP,SCTP)。基于流的传输协议负责流内数据的顺序,先发送出去的数据块总是早于后发送出去的数据块到达。基于包的传输传递数据,数据之间无任何依赖,并不维护数据之间的顺序。例如,一个数据块在网络中丢失了然后重发了,应用程序可以在这个丢失数据块之后发送的数据块收到后收到这个重发的数据块,但是不需要额外的重发请求。

传输Magic

传输magic是一个cookie,一小段由栈指定的数据,可以与传输关联上(例如,Via头)。协议栈可以在包括<sofia-sip/tport.h>头文件前通过定义TP_MAGIC_T改变传输magic的类型。

传输操作

发送消息

tport_tsend()函数可以用来发送消息。此函数既可以被primary也可以被secondary传输对象调用。如果secondary传输被需要来发送消息,它会被创建和自动连接。

传输对象使用msg_iovec()函数从消息对象内获取到需要发送的数据。传输对象会试着使用一个函数su_vsend()发送所有的数据。如果函数调用失败了,例如发送缓冲区太小了,传输对象会在内部队列内创建一个指向消息对象的引用。

接收消息

当无连接的primary传输对象或secondary传输对象接收到了新数据,将会为这些数据分配一个新的消息对象。协议栈提供的工厂函数tpac_alloc()将会创建这个消息对象。接收到的数据会提供给消息对象,当一个消息处理完毕数据就被解析好了,然后消息对象被传递给创建传输对象时提供的tpac_recv()函数。

引用计数

为了销毁那些不再使用的连接,每个secondary传输对象需要知道是否还存在栈内的引用。当传输对象收到一个呼入请求以及传输对象需要使用发送响应消息时,或者希望在发送请求的连接上收到来自服务器的响应时,协议栈将会为传输对象创建一个引用。

注意:
即便tport模块内实现了引用计数,传输对象也不会缺省被定时器销毁,因为所有的协议栈并不能正确地处理引用计数。当 TPTAG_IDLE()tag被使用时,定时器被激活。

挂起请求

协议栈使用tport_pend()函数给请求打上挂起标记。tport_pend()函数会将请求消息与回调函数关联上,以及一个句柄与客户端对象关联上。当传输对象出现错误后,将使用关联上的回调函数报告给客户端对象。

当栈接收到一个请求的响应后它将通过tport_release()函数为请求标记成挂起。如果响应是个预备性的消息,那么请求仍处于挂起状态。这种情况下,still_pending参数为真。如果栈不再关心任何响应消息,例如在超时后,即便没有响应消息tport_release()函数也会被调用。

发送队列

每个基于流的传输都支持发送队列。队列会在这样一些情况下使用:网络拥挤时消息入队列等待,或者维持响应消息的相对顺序。通常,队列被隐式使用,例如,如果一个传输忙着发送消息当调用tport_tsend() 函数时消息会被放入队列。

当协议(例如HTTP/1.1)需要响应消息的相关顺序必须保证时显式入队列就是必须的。当协议栈接收到一个请求,它使用tport_tqueue()函数将一个空的响应消息放入传输的队列中。这样一个空的响应消息被标记为未完成的,未做好发送准备。当应用程序通过tport_tqsend(),函数响应了一个请求,传输对象标记消息未准备好发送。如果队列内之前没有其他的响应消息,那么发送这个响应消息。

日志和转储消息

调试协议时查看日志内容和网络事件非常有帮助。有一些环境变量可以用来激活tport模块内消息日志。

TPORT_LOG
设置后tport模块在解析后打印消息内容
TPORT_DUMP
包含转储文件名称 - 解析前收到的数据写入转储文件内
TPORT_DEBUG
整数,取值范围:-1..9,控制tport模块调试信息的输出。可以参考tport_log。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值