RFC3261(17 事務)

????SIP是一個基于事務處理的協議:部件之間的交互是通過一系列相互獨立的消息交換來完成的。特別是,一個SIP?事務由一個單個請求和這個請求的所有應答組成,這些應答包括了零個或者多個臨時應答以及一個或者多個終結應答。在事務中,當請求是一個INVITE(叫做INVITE事務),當終結應答不是一個2xx應答的時候,事務還包括一個ACK。如果應答是一個2xx應答,那么ACK并不認為是事務的一部分。

????這個分開的原因是基于傳遞全部200(OK)應答到UAC的INVITE請求的重要性所決定的。要把所有的200應答全部發給UAC,UAS獨自負責這些應答的重新傳送(參見13.3.1.4),UAC獨自負責這些應答的ACK確認(參見13.2.2.4)。由于ACK的重傳只由UAC發起,所以在自己的事務中進行重傳會比較有效。

????事務分為客戶端和服務端兩方。客戶端的事務是客戶端事務,服務器端的事務就是服務端事務。客戶端事務發出請求,并且服務端事務送回應答。客戶端和服務端事務都是邏輯上的概念,他們可以被無數部件所包含。特別是,它們在UA中和有狀態的proxy服務器中存在。以第4節的例子來說,在這個例子中,UAC執行客戶端事務,它的外發proxy執行服務端事務。外發proxy同時也執行客戶端事務,把請求發送到一個另一端proxy的服務端事務。這個proxy也同時執行一個客戶端事務,把請求發到一個UAS的服務端事務上去。如圖4所示:

?

?

圖4:?事務關系

????無狀態的proxy并沒有客戶端或者服務端的事務。事務是一邊基于UA或者有狀態的proxy,另外一邊也基于UA或者有狀態的proxy。就SIP事務而言,無狀態的proxy實際上實現透明傳輸。客戶端事務用于從一個元素中接收一個請求,這個客戶端是內嵌的(這個元素就是“事務用戶”或者TU;它可以是一個UA或者有狀態的proxy),并且可靠的把這個請求傳送到一個服務端事務。

????客戶端事務也負責接收應答并且把應答轉交TU處理,過濾掉重發的應答或者不允許的應答(比如給ACK的應答)。另外,在INVITE請求的情況下,客戶端事務也負責產生給2xx應答的ACK請求。

????類似的,服務端事務也負責從通訊層接收請求并且轉發這個請求到TU。服務端事務過濾重發的請求。并且服務端事務從TU接收應答并且轉發到通訊層來發送。在INVITE事務的情況下,它需要接收給非2xx應答的終結應答的ACK請求。

????2xx應答和它的ACK請求通過特定的方式來接收和處理。這個應答只會被UAS重發,并且它的ACK只由UAC產生。由于呼叫者知道整個已經接收呼叫的用戶集合,所以需要這種端到端的處理。由于這樣的特別處理,2xx應答的重發是基于UA核心的,并非基于通訊層。類似的,給2xx應答的ACK處理也是由UA核心處理的,每個路徑上的proxy僅僅轉發這些INVITE的2xx應答以及他們的ACK。

17.1?客戶端事務

???客戶端事務是通過維持一個狀態機來提供服務的。

???TU和客戶端事務通過一個簡單的接口進行通訊。當TU希望初始化一個新的事務,它創建一個客戶端事務并且通過設置ip地址、端口和transport來把一個SIP請求交給它傳送。然后客戶端事務開始執行它自己的狀態機。合乎規格的應答會從客戶端事務傳送給TU。

???總共有兩種類型的客戶端事務狀態機,根據TU傳遞的請求的方法不同來區分。一個用于處理INVITE請求。這種狀態機對應的是一個INVITE客戶事務。另外一個是用來處理其他所有的非INVITE請求的。它對應的是非INVITE客戶事務。對于ACK來說,是不存在客戶事務的。如果TU希望送一個ACK請求,它直接交給通訊層進行通訊處理。

???INVITE事務和其他事務是不同的,因為它的時間周期很長。通常,對于INVITE請求的應答來說,都需要人的參與,這樣會導致在應答INVITE請求之前會有很長的延時。在三方握手(人,兩方機器)的時候也會有很長的延時。在另一方面,其他請求的響應都是很快就完成的。因為其他非INVITE請求事務是雙方的握手,TU能夠立刻對非INVITE請求作出應答。

17.1.1?INVITE客戶事務
17.1.1.1?INVITE事務概述

???INVITE請求包含了一個三次握手。客戶端事務發送一個INVITE,服務端事務回送一個應答,客戶端事務發送一個ACK。對于非可靠傳輸(比如UDP),客戶端事務每隔T1重發請求,每次重發后間隔時間加倍。T1是一個估計的循環時間(RTT),缺省設置成為500ms。幾乎所有的事務定時器都以T1為單位,并且調整T1的值也就調整了那些定時器的值。請求不會在可靠的通訊協議上重新發送。在接收到1xx應答以后,重發機制完全停止,并且客戶端等待更進一步的應答。服務端事務可以發送附加的1xx應答,這個應答并非由服務端事務可靠傳輸。最后,服務端事務會發送一個終結應答。對于非可靠的傳輸協議,應答會間隔時間來重發,對于可靠的傳輸協議,它只發送1次。對于客戶端事務所接收的每一個終結應答,客戶端事務都發送一個ACK,用于終止應答的重發送。

17.1.1.2?正式的描述

???INVITE客戶端事務的狀態機在圖5中展示。初始狀態“calling”,必須保證TU是用INVITE請求來初始化一個新的客戶端事務。客戶端事務必須把請求發送到通訊層來進行發送(18節)。如果使用的是非可靠傳輸的通訊層,客戶端事務必須啟動一個定時器A并且由缺省值T1組成。如果是一個可靠的通訊協議,那么客戶端事務不應當啟動定時器A(定時器A控制請求的重發送)。對于任何通訊協議來說,客戶端事務必須啟動一個定時器B并且有著64×T1秒的缺省值(定時器B控制事務的超時)。

???當定時器A觸發了,客戶端事務必須重發這個請求,把請求交給通訊層進行發送,并且重新設置定時器為2*T1。在傳輸層中重傳的定義是指把剛才通過傳輸層發送的消息,再次交給傳輸層重新發送一次。

???當定時器A在2×T1后觸發了,請求必須再次重傳(如果客戶端事務依舊還是在這個狀態的話)。這個處理必須持續下去,這樣請求才能每重發一次以后定時器延時1倍。重發機制只有當客戶端事務在”calling”狀態的時候才能進行。

???缺省的T1是500ms。T1是一個客戶端和服務端間事務處理的估計時間TIT。節點可以(不推薦)使用更小的T1值,比如通常不接入Internet的私有網絡。T1也可以設置成為大一點的值,并且我們建議如果當我們知道RTT值比較大的時候(比如高延時的網絡)應當設置T1成為大一點的值。不管T1如何取值,本節要求的重傳機制指數延時是必須使用的。

???當定時器B觸發的時候,如果客戶端事務依舊在”calling”狀態,那么客戶端事務應當通知TU發生了超時。客戶端事務必須不能產生ACK。64×T1是和在不可靠通訊鏈路上傳輸7個請求的時間相同。

???如果客戶端事務在”calling”狀態接收到一個臨時應答,那么就把狀態切換到“proceeding”狀態,客戶端事務不應當再次重新發送請求了。進一步說,臨時應答必須傳送給TU。在“proceeding”狀態的任何臨時應答都必須傳送給TU。

???在“calling”或者“proceeding”狀態的時候,如果接收到一個應答碼是300-699的應答,那么就必須把狀態切換到”Completed”。客戶端事務必須把收到的應答轉給TU,并且客戶端事務必須產生ACK請求,即使通訊層是可靠傳輸的(在17.1.1.3節中有描述怎樣根據應答創建一個ACK請求)并且把ACK交給傳輸層進行傳送。ACK必須和原始請求發送到相同的地址、端口和transport。當客戶端事務進入“Completed”狀態的時候,應當開始一個定時器D,缺省值是在非可靠通訊上是至少32秒,在可靠通訊上是0秒。定時器D反應了服務端事務在非可靠傳輸的情況下,在“completed”狀態維持的時間。這個是和INVITE請求服務端事務定時器H相同的,定時器H的缺省值是64*T1。不過,客戶端事務不知道服務端事務使用的T1值,所以我們用絕對值32秒來代替T1用作定時器D的缺省值。

???在“completed”狀態下,收到的任何終結應答的重傳都應當產生一個ACK應答到通訊層來重新發送,但是新近收到的應答卻不能傳送給TU。一個應答是否是重傳的定義是根據這個應答是否和客戶端事務按照17.1.3定義的規則匹配。

圖5:?INVITE客戶端事務

?

???如果在客戶端事務狀態是“Completed”的時候,定時器D觸發,那么客戶端事務必須轉到終結狀態。當客戶端狀態是”calling”或者“proceeding”狀態的時候,接收到一個2xx應答必須導致客戶端事務進入“terminated”狀態,并且應答必須交給TU處理。處理這個應答的方法依賴于TU是否是一個proxy核心還是是UAC核心。UAC核心會給應答產生ACK,proxy核心會轉發一個200(OK)應答到上行隊列。這個在proxy和UAC之間,對200(OK)的不同的處理是導致對應答的處理不在事務層進行的原因。

???當客戶端事務進入“terminate”狀態以后,客戶端事務必須立刻銷毀。這樣才能保證正確操作。原因是當給一個INVITE請求的2xx應答的不同處理;對于proxy轉發的時候和對UAC處理ACK的時候是不一樣的。因此,每一個2xx都需要交給proxy?核心(這樣才能被轉發),或者交給UAC核心(這樣才能被ACK確認)。這期間沒有事務層的處理。無論應答是否由通訊層收到,如果通訊層找不到匹配的客戶端事務(用17.1.3的方式),那么應答就應當交給核心處理。這是由于與之匹配的客戶端事務已經被第一個2xx應答所銷毀,后續的2xx應當就匹配不成功了,于是就交給核心來處理。

17.1.1.3?構造ACK請求

???本節定義了在客戶端事務中構造ACK請求的方法。UAC核心為2xx應答產生ACK請求必須使用13節描述的方法,而不是用下邊的方法。

???在客戶端事務中構造的ACK請求必須包括與原始請求相同的Call-ID、From、Request-URI頭域值(就是說和在客戶端事務發到通訊層的請求中的這些頭域值相同)。在ACK請求中的To頭域必須和被確認的應答的To頭域值相同,因此通常和原始請求有所不同,不同點在增加了附加的tag參數。ACK必須包含一個單個的Via頭域,并且必須和原始請求的最上邊一個Via頭域值相等。ACK的Cseq頭域必須包含和原始請求的Cseq的序列號相同,但是方法參數應當是”ACK”。

???如果INVITE請求的應答是有Route頭域的,這些Route頭域必須也在ACK中。這是確保ACK能夠正確路由通過下行隊列的無狀態的proxy。

???雖然請求可以包含一個包體,但是ACK的包體卻比較特別,因為請求不能因為不能理解包體而拒絕這個請求。因此,我們不建議在給非2xx應答的ACK請求中放置包體,但是如果放置了,并且假設給INVITE的應答不是415應答,那么包體的類型應當嚴格和INVITE請求中定義的那樣。如果是415應答,那么ACK的包體應當和415應答中的Accept列出的類型一致。

?

例如:有如下請求

INVITE?sip:bob@biloxi.com?SIP/2.0

Via:?SIP/2.0/UDP?pc33.atlanta.com;branch=z9hG4bKkjshdyff

To:?Bob?<sip:bob@biloxi.com>

From:?Alice?<sip:alice@atlanta.com>;tag=88sja8x

Max-Forwards:?70

Call-ID:?987asjd97y7atg

Cseq:?986759?INVITE

?

給非2xx終結應答的ACK請求應當是:

ACK?sip:bob@biloxi.com?SIP/2.0

Via:?SIP/2.0/UDP?pc33.atlanta.com;branch=z9hG4bKkjshdyff

To:?Bob?<sip:bob@biloxi.com>;tag=99sa0xk

From:?Alice?<sip:alice@atlanta.com>;tag=88sja8x

Max-Forwards:?70

Call-ID:?987asjd97y7atg

Cseq:?986759?ACK

?

17.1.2?非INVITE客戶端事務
17.1.2.1?非INVITE事務概覽

???非INVITE事務并不使用ACK。他們只是簡單的請求-應答的交互。對于非可靠的通訊來說,請求是間隔倍增T1的時間重新傳輸(直到間隔時間達到T2)。如果收到了一個臨時應答,在非可靠通訊上,重傳繼續直到達到T2。只有當重傳的請求收到的時候,服務端事務會重傳其發出的最后一個應答,既可以是臨時的應答也可以是終結應答。這就是為什么請求在收到一個臨時應答之后還需要一直重傳的原因;他們能夠確保收到一個終結應答。

???不像INVITE事務,非INVITE事務不需要對2xx應答做特別處理。UAC對一個非INVITE請求來說,只會產生一個單個的2xx應答。

17.1.2.2?正式的描述

???在圖6中講述了非INVITE客戶端事務的狀態機。這個狀態機和INVITE客戶端事務的狀態機非常像。

???當TU用請求來初始化一個新的客戶端事務的時候,首先進入的是“trying”狀態。當進入這個狀態的時候,客戶端事務應當初始化一個定時器F,這個定時器F應當有一個初始值64×T1秒。這個請求必須交給通訊層來發送。如果使用的是非可靠傳輸的通訊協議,客戶端事務必須還設置定時器E,初始值是T1。如果定時器E觸發了,并且還是在“trying”狀態,那么定時器需要設置成為MIN(2*T1,T2),并且重新發送;如果再次觸發了,那么就再設置成為MIN(4*T1,T2),每次都是倍增,直到T2。這個過程會一直繼續,直到重發的間距是T2為止。缺省的T2是4秒,并且它大概是一個在沒有立刻響應的情況下,非INVITE服務端事務處理一個請求的時間。根據缺省的T1和T2,那么間隔就會是:500ms,1s,2s,4s,4s,4s以次類推。

???如果定時器F觸發了,并且客戶端事務依舊是在“trying”狀態,那么客戶端事務應當通知TU這個超時,并且轉入“terminate”狀態。如果在“trying”狀態的時候收到了一個臨時應答,那么這個應答必須轉給TU處理,并且客戶端事務轉到“proceeding”狀態。如果在“trying”狀態收到了一個終結應答(200-699的應答碼),那么應答必須交給TU,并且客戶端事務必須轉到“Completed”狀態。

???如果定時器E在”Proceeding”狀態觸發了,那么請求必須交給通訊層進行傳輸,并且定時器E必須重新設置成為T2秒。如果定時器F在”Proceeding”狀態觸發了,那么必須通知TU超時了,并且客戶端事務必須轉到終結狀態。如果在”Proceeding”狀態的時候收到了一個終結應答(狀態碼200-699),這個應答必須發送給TU,并且客戶端事務必須轉到”Completed”狀態。

???一旦客戶端事務進入“Completed”狀態,對于非可靠傳輸的情況,客戶端事務必須設置一個定時器K=T4秒,對于可靠傳輸的情況,設置定時器K=0秒。這個“Completed”狀態維持的目的是為了緩沖可能會收到的其他重發的應答(這是為什么客戶端事務在這里為非可靠傳輸維持一段時間的原因)。T4代表了網絡在客戶端和服務端事務中傳輸信息可能的時間。缺省的值T4=5秒。當應答具有相同的事務匹配的時候,根據17.1.3的判定,這個應答就是重發的應答。如果定時器K在這個狀態被觸發,客戶端事務必須轉到“Terminate”狀態。

???當事務進入終結狀態,就必須立刻終止了。

?

圖6:?非INVITE客戶端事務

17.1.3?客戶端事務匹配應答

???當客戶端事務的通訊層收到一個應答,他必須決定是否由客戶端事務來處理這個應答,這樣17.1.1和17.1.2才能夠正確執行。在Via頭域的最上邊的branch參數就是用來做這個的。一個應答和一個客戶端事務匹配的話,就有兩個條件:

1、?如果應答Via最上邊的branch參數和創建這個客戶端事務的請求的Via最上邊的branch參數相同。

2、?如果Cseq頭域的方法參數和創建事務的請求的方法相同。這是因為CANCEL方法的事務和源請求的事務不同,但是卻有相同的branch參數所決定的。

????如果一個請求是廣播發送的,他可能從不同的服務器上得到不同的應答。這些應答的最上邊的Via都有相同的branch參數,但是在To?tag中是不同的。當收到了第一個應答,基于上邊的規則,將會判定是這個客戶端事務的應答,其他的應答將會視同為重發。這并不是錯誤的情況;多點傳送SIP只是提供了一個初步的“尋找最接近的單點”服務的方法,這樣就限定了只需要處理單個應答。詳情參見18.1.1。

17.1.4?處理通訊錯誤。

???當客戶端事務發送一個請求到通訊層發送的時候,如果通訊層報告發送失敗,那么需要執行下列步驟。

???客戶端事務應當通知TU這個通訊失敗,并且客戶端事務應當直接轉到“Terminate”狀態。TU處理通訊失敗的機制在附件[4]中描述。

?

17.2?服務端事務

???服務端事務是用來傳輸請求到TU并且可靠的傳輸應答的。它是通過狀態機來實現的。服務端事務是當請求到達的時候由核心創建的,事務的處理也是主要圍繞著對應請求的(也就是說并非全部都是和對應請求相關)。

???和客戶端事務對應的,狀態機依賴于是否接收的請求是INVITE請求。

17.2.1?INVITE服務端事務

????INVITE服務端事務的狀態圖在圖7表達。

????當為一個請求創建了服務端事務的時候,服務端事務進入“proceeding”狀態。除非服務端事務知道TU在200ms之內會生成臨時或者終結應答(在這種情況下,TU可能會產生100Trying應答),他必須生成100(Trying)應答。這個臨時應答是用來停止客戶端重發請求的,這個可以避免網絡風暴。這個100(Trying)應答是根據8.2.6節描述的步驟構造的,除此之外:?如果接收的請求頭中的To頭域沒有tag標志,那么原來描述的可以增加tag標記,更改成為不應該增加tag標志。這個請求必須交給TU處理。

????TU可以給服務端事務任意數量個臨時應答。只要服務端事務在“proceeding”狀態,每個臨時應答都應當交給通訊層發送。這些臨時應答并非被通訊層可靠的發送(它們并不重新發送臨時應答)并且臨時應答并不改變服務端事務的狀態。如果在“proceeding”狀態,收到一個請求的重發請求,那么就需要把從TU最近收到的那個臨時應答重新交給通訊層發送一次。請求是否是重發的請求,是基于17.2.3來判定的匹配相同服務端事務的請求。

????如果,在“proceeding”狀態,TU發送了一個2xx應答給服務端事務,服務端事務必須把這個應答交給通訊層進行發送。這個并非由服務端事務進行重發;對于2xx應答的重發是由TU處理的。服務端事務必須轉到“Terminated”狀態。

????當在“Proceeding”狀態的時候,如果TU交給服務端事務一個300到699的應答,那么應答必須交給通訊層進行發送,并且狀態機必須進入“Completed”狀態。對于非可靠傳輸的情況,必須設置定時器G=T1秒,對于可靠傳輸的情況,不設置定時器G(=0的情況就是不設置)

這個是和RFC2543所不同的,2543要求應答都要重發,甚至在可靠傳輸的情況下。

當進入了“Completed”狀態,必須為所有的傳輸設置一個定時器H=64×T1秒。定時器H決定何時服務端事務取消重發應答。這個值和定時器B的取值一樣,是等同于客戶端事務會重試發送請求的時間。如果定時器G觸發了,那么應答會交給通訊層再次發送,并且定時器設置成為MIN(2*T1,T2)秒。依此類推,當定時器G再次觸發,那么定時器G的值會翻倍,直到T2。這個和非INVITE客戶端事務的”trying”請求的重發機制是一樣的。進一步說,當在“Completed”狀態的時候,如果接收到重發的請求,服務端事務應當把應答交給通訊層再次發送。

????當服務端事務在“Completed”狀態的時候,如果收到了一個ACK請求,服務端事務必須轉到“Confirmed”狀態。因為定時器G會在這個狀態被忽略,所有的應答重發都會被終止。

????如果在“completed”狀態的時候定時器H觸發了,就意味著沒有收到ACK請求。在這個情況下,服務端事務必須轉到“Terminated”狀態,并且必須通知TU事務失敗。

?

圖7:INVITE服務端事務

?

????設定“Confirmed”狀態的目的是為了處理任何附加的ACK消息,這是由重發的終結應答所觸發的。當進入這個狀態,如果是在不可靠傳輸協議,那么就要設定一個定時器I=T4秒,如果是可靠傳輸協議,那么就設定I=0。當定時器I觸發了,服務端事務必須轉到“Terminated”狀態。

????當服務端事務狀態處于“Terminated”狀態,這個事務必須立刻銷毀。和客戶端事務一樣,這是為了保證給INVITE的2xx應答的可靠性。

17.2.2?非INVITE服務端事務

????對非INVITE服務端事務的狀態機是在圖8中表示。

????當收到一個不是INVITE或者ACK的請求的時候,狀態機會初始化成為“trying”狀態。并且這個請求會交給TU處理。當在“trying”狀態,任何重發的請求會被忽略。一個請求在通過17.2.3節的步驟,匹配現有的服務端事務,將被認為是重發的請求。

????當處于“trying”狀態,如果TU交給服務端事務一個臨時應答,服務端事務應當進入“Proceeding”狀態。這個應答必須交給通訊層進行發送。在“Proceeding”狀態下從TU收到的任何應答都必須交給通訊層進行發送。如果一個重發的請求在“proceeding”狀態下收到了,那么最近發出的一個臨時應答應當再次交給通訊層進行重發。如果在“Proceeding”狀態下,TU交給服務端事務一個終結應答(應答碼是200-699),那么服務端事務必須進入“Completed”狀態,并且應答必須交給通訊層進行發送。

????當服務端事務進入了“Completed”狀態,對于不可靠傳輸協議來說,必須設定一個定時器J=64×T1秒,對于可靠傳輸來說,設定為0秒(就是不設定定時器)。在“Completed”狀態下,當服務端事務收到了一個重發請求的時候,服務端事務必須交給通訊層終結應答來重新發送。在“Completed”狀態下,任何其他TU傳遞下來給服務端事務的終結應答都必須被拋棄。服務端事務保持這個狀態直到定時器J觸發,當定時器J觸發了以后,服務端事務必須進入“Terminated”狀態。

圖8:?非INVITE?服務端事務

17.2.3?為服務端事務匹配請求。

????當服務端從網絡上收到一個請求以后,他必須和現有的事務進行判定。這個是根據下邊的規則來判定的。

????首先要檢查請求中的Via頭域的最上一個branch參數。如果他以”z9hG4bk”開頭,那么這個請求一定是由客戶端事務根據本規范產生的。因此,branch參數在該客戶端發出的所有事務中都是唯一的。根據下列規則我們可以判定請求是否和事務匹配:

1、?請求中的最上的Via頭域的branch參數和創建本事務的請求的最上的Via頭域的branch參數一樣,并且:

2、?請求的最上的Via頭域的sent-by參數和創建本事務的請求的最上的Via頭域的send-by參數一樣,并且:

3、?請求的方法和創建本事務的方法一樣。這有一個例外,就是ACK,ACK對應的創建本事務的請求方法是INVITE。

這個匹配規則用于INVITE和非INVITE事務。

send-by參數被用于匹配過程,這是因為有可能存在無意/惡意的相同的不同客戶端傳來的branch參數。

????如果最上的Via頭域的branch參數不存在,或者沒有包含那個”z9hG4bk”,那么就用下列步驟進行判定。這是為了和RFC2543進行兼容的。

????如果是INVITE請求,并且這個INVITE請求的Request-URI、To?tag、From?tag、Call-ID、Cseq和最上的Via頭域都和創建事務的INVITE請求的這些字段匹配,那么這個INVITE請求就是匹配這個事務的INVITE請求。在這個情況下,INVITE就是創建這個事務的INVITE請求的一個重發。ACK請求在匹配創建事務的INVITE請求的Request-URI、From?tag、?Call-ID、Cseq序列號(非方法字段)、?最上的Via頭域、并且To?tag和服務端事務發出的應答的To?tag相同,這個ACK就是這個事務的ACK。當這些頭域比較完成,那么這個匹配也就完成了。在ACK比較中包含To?tag的比較是為了在proxy上能夠區別給2xx的ACK和給其他應答的ACK,這個proxy可能會轉發全部的應答(這個會在某種罕見的情況下發生。特別是,當一個proxy分支一個請求,接著宕機了,應答會轉發到別的proxy,這個proxy可能會終止轉發多重應答到上行隊列)。一個匹配INVITE請求事務的ACK請求,如果這個INVITE請求已經被前一個ACK請求所匹配,那么這個ACK請求就是上一個ACK請求的重發。

????對于所有的其他請求方法,如果請求的Request-URI、To?tag、From?tag、Call-ID、?Cseq(包括Cseq中的方法字段),以及Via頭域的最上值,都和創建服務端事務的請求想匹配,那么這個請求就是這個事務的匹配請求。匹配是基于針對每一個頭域值的判定進行的。當非INVITE請求和現有事務匹配了,那么它就是創建這個事務的請求的一個重發。

????由于匹配規則中包含了Request-URI,服務器不能匹配應答對應到事務。所以當TU傳送了一個應答到服務端事務,它必須為這個應答指定傳送到那個服務端事務。

17.2.4?處理通訊錯誤

????當服務端事務發送一個應答到通訊層要發送的時候,如果通訊層報告發送失敗,那么就需要執行下列的步驟:

????首先,附件[4]的步驟需要執行,這就是說需要把應答發送一個備份的地點。如果這個也失敗了,基于[4]中對失敗的定義,服務端事務應當通知TU發送失敗,并且把狀態切換到終止狀態。

轉載于:https://www.cnblogs.com/share-everything-i-do/archive/2012/11/07/2759555.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377115.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377115.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377115.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HDUOJ---1754 I Hate It (線段樹之單點更新查區間最大值)

I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 33469 Accepted Submission(s): 13168 Problem Description很多學校流行一種比較的習慣。老師們很喜歡詢問&#xff0c;從某某到某某當中&#xff0c;…

WEG的完整形式是什么?

WEG&#xff1a;邪惡邪惡的咧嘴 (WEG: Wicked Evil Grin) WEG is an abbreviation of "Wicked Evil Grin". WEG是“ Wicked Evil Grin”的縮寫 。 It is also known as EWG (Evil Wicked Grin) "Grin" refers to a broad smile. "Wicked" refer…

C# 把數字轉換成鏈表

例如&#xff1a;123456轉換成 1 -> 2 -> 3-> 4-> 5-> 6 View Code static LinkedList<int> CovertIntToLinkedList(int num){Stack<int> stack new Stack<int>();LinkedList<int> result new LinkedList<int>();while (num!0…

《MySQL 8.0.22執行器源碼分析(4.1)Item_sum類以及聚合》

Item_sum類用于SQL聚合函數的特殊表達式基類。 這些表達式是在聚合函數&#xff08;sum、max&#xff09;等幫助下形成的。item_sum類也是window函數的基類。 聚合函數&#xff08;Aggregate Function&#xff09;實現的大部分代碼在item_sum.h和item_sum.cc 聚合函數限制 不…

Java 性能優化實戰記錄(2)---句柄泄漏和監控

前言: Java不存在內存泄漏, 但存在過期引用以及資源泄漏. (個人看法, 請大牛指正) 這邊對文件句柄泄漏的場景進行下模擬, 并對此做下簡單的分析.如下代碼為模擬一個服務進程, 忽略了句柄關閉, 造成不能繼續正常服務的小場景. 1 public class FileHandleLeakExample {2 3 p…

什么是Java文件?

Java文件 (Java files) The file is a class of java.io package. 該文件是java.io包的類。 If we create a file then we need to remember one thing before creating a file. First, we need to check whether a file exists of the same name or not. If a file of the sa…

繞過本地驗證提交HTML數據

我們在入侵一個網站,比如上傳或者自己定義提交的文件時,會在本地的代碼中遇到阻礙,,也就是過 濾,過濾有兩種,一種是在遠程服務器的腳本上進行的過濾,這段代碼是在服務器上運行后產生作用的,這種過 濾方式叫做遠程過濾;另一種是在我們的IE瀏覽器里執行的腳本過濾,就是說是在我們…

《dp補卡——343. 整數拆分、96. 不同的二叉搜索樹》

343. 整數拆分 1、確定dp數組以及下標含義。 dp[i]&#xff1a;分拆數字i&#xff0c;可以得到的最大的乘積 2、確定遞推公式&#xff1a; dp[i]最大乘積出處&#xff1a;從1遍歷j到i&#xff0c;j * dp[i-j] 與 j * (i-j)取最大值。( 拆分j的情況&#xff0c;在遍歷j的過程…

Adroid學習之 從源碼角度分析-禁止使用回退按鈕方案

有時候&#xff0c;不能讓用戶進行回退操作&#xff0c;如何處理&#xff1f; 查看返回鍵觸發了哪些方法。在打開程序后把這個方法禁止了。問題&#xff1a;程序在后臺駐留&#xff0c;這樣就會出現&#xff0c;其他時候也不能使用回退按鈕。如何處理&#xff0c;在onpase()時方…

騎士游歷問題問題_騎士步行問題

騎士游歷問題問題Problem Statement: 問題陳述&#xff1a; There is a chessboard of size NM and starting position (sx, sy) and destination position (dx,dy). You have to find out how many minimum numbers of moves a knight goes to that destination position? 有…

Android基礎之用Eclipse搭建Android開發環境和創建第一個Android項目(Windows平臺)...

一、搭建Android開發環境 準備工作&#xff1a;下載Eclipse、JDK、Android SDK、ADT插件 下載地址&#xff1a;Eclipse:http://www.eclipse.org/downloads/ JDK&#xff1a;http://www.oracle.com/technetwork/java/javase/downloads/jdk7u9-downloads-1859576.html Android SD…

《dp補卡——01背包問題》

目錄01背包[416. 分割等和子集](https://leetcode-cn.com/problems/partition-equal-subset-sum/)[1049. 最后一塊石頭的重量 II](https://leetcode-cn.com/problems/last-stone-weight-ii/)[494. 目標和](https://leetcode-cn.com/problems/target-sum/)01背包 1、dp數組以及…

用JavaScript往DIV動態添加內容

參考&#xff1a;http://zhidao.baidu.com/link?url6jSchyqPiEYCBoKdOmv52YHz9r7MTBms2pK1N6ptOX1kaR2eg320mlW1Sr6n36hpOeOadBxC2rWWGuhZPbms-K <div id"show"></div>要填充的數據為: 這是一個測試例子.jquery&#xff1a;$(function(){ var data …

《dp補卡——完全背包問題》

N件物品和一個最多能背重量為W的背包。第i件物品的重量為weight[i]&#xff0c;得到的價值是value[i]。每件物品都有無限個(可以放入背包多次)&#xff0c;求解將哪些物品裝入背包里物品價值總和最大。 01背包和完全背包唯一不同在于遍歷順序上。 01背包的核心代碼&#xff1a…

Java中的類型轉換

類型轉換 (Typecasting) Typecasting is a term which is introduced in all the language similar to java. Typecasting是一個用與Java類似的所有語言引入的術語。 When we assign primitive datatype to another datatype. 當我們將原始數據類型分配給另一個數據類型時。 I…

讓crash文件中的內存地址變成函數名稱,

假如程序員編譯了inhouse給測試。 如果在測試過程中出現奔潰現象&#xff0c;我想程序員一般會來看Device Log 也就是 crash文件 如果crash文件遇到如下的情況&#xff0c;在重要的地方看不到函數名稱。我想是一件很奔潰的事情。 1 Exception Type: EXC_BAD_ACCESS (SIGSEGV)2…

《dp補卡——多重背包》

多重背包簡介&#xff1a; 有N種物品和一個容量為V的背包。第i種物品最多有Mi件可用&#xff0c;每件耗費的空間為Ci&#xff0c;價值為Wi。求解將哪些物品裝入背包可使得這些物品耗費的空間總和不超過背包容量&#xff0c;且價值總和最大。 將Mi件攤開&#xff0c;就是一個01背…

kafka消息確認ack_什么是確認(ACK)? ACK代表什么?

kafka消息確認ackACK&#xff1a;致謝 (ACK: Acknowledgment) An acknowledgment (ACK) is a signal that is passed among the communicating processes, computers, or devices to indicate acknowledgment, or delivery of the message, as a component of a communications…

CocoaAsyncSocket 套接字

CocoaAsyncSocket 套接字 https://github.com/robbiehanson/CocoaAsyncSocket Asynchronous socket networking library for Mac and iOS 用于iOS以及Mac的異步套接字網絡庫。 TCP GCDAsyncSocket and AsyncSocket are TCP/IP socket networking libraries. Here are the key…

谷歌瀏覽器設置緩存方法

谷歌瀏覽器設置緩存方法&#xff1a; 1、在桌面Google Chrome快捷方式&#xff0c;目標&#xff1a;找到 C:\Users\Splendid\AppData\Local\…\Application\chrome.exe 在這后面加上-Disk-Cache-Dir”Z:\TEMP” 注意: -Disk前面有空格&#xff0c;”Z:\TEMP” 是文件存放在Z盤T…