概述
傳輸層通信協(xié)議
SCTP 被視為一個傳輸層協(xié)議姥饰,它的上層為SCTP 用戶應(yīng)用幕与,下層作為分組網(wǎng)絡(luò)界牡。在SIGTRAN 協(xié)議的應(yīng)用中秒咐,SCTP 上層用戶是SCN 信令的適配模塊(如M2UA、M3UA)盈简,下層是IP 網(wǎng)拳话。
兩種最流行的傳輸層協(xié)議是傳輸控制協(xié)議 (TCP) 和用戶數(shù)據(jù)報協(xié)議 (UDP):
- TCP 是一種可靠的協(xié)議,可確保有序镜盯、有序地傳遞數(shù)據(jù)并管理網(wǎng)絡(luò)中的擁塞。
- UDP 是一種面向消息的協(xié)議艺糜,既不能保證傳遞順序,也不能管理擁塞毅臊。
但是,UDP 是一種快速協(xié)議,用于保留它傳輸?shù)南⒌倪吔纭?/p>
本文提供了另一個選項:SCTP胎挎。它提供了可靠美浦、有序地傳遞數(shù)據(jù)(如 TCP)蹬竖,但以 UDP 等面向消息的方式運行,從而保留消息邊界。SCTP 還提供幾個高級功能:
- 多宿主
- 多流
- 啟動保護(hù)
- 消息框架
- 可配置的無序交付
- 優(yōu)雅關(guān)機(jī)
術(shù)語
傳送地址
傳送地址由 IP 地址阴绢、傳輸層協(xié)議類型和傳輸層端口號定義腺兴。由于SCTP 在IP 上傳 輸篓足,所以一個SCTP 傳送地址由一個IP 地址加一個SCTP 端口號決定枕扫。SCTP 端口 號就是SCTP 用來識別同一地址上的用戶,和TCP 端口號是一個概念参滴。比如IP 地 址10.105.28.92 和SCTP 端口號1024 標(biāo)識了一個傳送地址青灼,而10.105.28.93 和 1024 則標(biāo)識了另外一個傳送地址专普,同樣策橘,10.105.28.92 和端口號1023 也標(biāo)識了一 個不同的傳送地址蚌堵。
主機(jī)和端點
- 主機(jī)(HoST) 主機(jī)配有一個或多個 IP 地址,是一個典型的物理實體。
- 端點(SCTP Endpoint)
端點是SCTP 的基本邏輯概念藕夫,是數(shù)據(jù)報的邏輯發(fā)送者和接收者,是一個典型的邏 輯實體病蛉。
一個傳送地址(IP 地址+SCTP 端口號)唯一標(biāo)識一個端點。一個端點可以由多個 傳送地址進(jìn)行定義,但對于同一個目的端點而言沽瘦,這些傳送地址中的IP 地址可以配 置成多個,但必須使用相同的SCTP 端口。
關(guān)聯(lián)和流
關(guān)聯(lián)(AssociaTIon)
關(guān)聯(lián)就是兩個 SCTP 端點通過SCTP 協(xié)議規(guī)定的4 步握手機(jī)制建立起來的進(jìn)行數(shù)據(jù)傳遞的邏輯聯(lián)系或者通道喇颁。 SCTP 協(xié)議規(guī)定在任何時刻兩個端點之間能且僅能建立一個關(guān)聯(lián)殖属。由于關(guān)聯(lián)由兩個端點的傳送地址來定義原环,所以通過數(shù)據(jù)配置本地IP 地址嘱吗、本地SCTP 端口號哆致、對端 IP 地址、對端SCTP 端口號等四個參數(shù),可以唯一標(biāo)識一個SCTP 關(guān)聯(lián)豌鹤。正因為如 此愿卸,在GTSOFTX3000 中,關(guān)聯(lián)可以被看成是一條M2UA 鏈路或M3UA 鏈路。
流(Stream)
流是 SCTP 協(xié)議的一個特色術(shù)語涛碑。SCTP 關(guān)聯(lián)中的流用來指示需要按順序遞交到高 層協(xié)議的用戶消息的序列揉阎,在同一個流中的消息需要按照其順序進(jìn)行遞交毙籽。嚴(yán)格地 說巡扇,“流”就是一個SCTP 關(guān)聯(lián)中,從一個端點到另一個端點的單向邏輯通道。一 個關(guān)聯(lián)是由多個單向的流組成的甸昏。各個流之間相對獨立徐许,使用流ID 進(jìn)行標(biāo)識,每個 流可以單獨發(fā)送數(shù)據(jù)而不受其他流的影響。
通路(Path)和首選通路(Primary Path)
通路(Path)
通路是一個端點將 SCTP 分組發(fā)送到對端端點特定目的傳送地址的路由吨枉。如果分組發(fā)送到對端端點不同的目的傳送地址時貌亭,不需要配置單獨的通路。
首選通路(Primary Path)
首選通路是在默認(rèn)情況下胯陋,目的地址凉翻、源地址在SCTP 分組中發(fā)到對端端點的通路男杈。
如果可以使用多個目的地地址作為到一個端點的目的地址伶棒,則這個SCTP 端點為多 歸屬舅锄。如果發(fā)出SCTP 分組的端點屬于多歸屬節(jié)點時,如果定義了目的地址皇忿、源地 址鳍烁,能夠更好控制響應(yīng)數(shù)據(jù)塊返回的通路和數(shù)據(jù)包被發(fā)送的接口姚垃。 一個 SCTP 關(guān)聯(lián)的兩個SCTP 端點都可以配置多個IP 地址看成,這樣一個關(guān)聯(lián)的兩個 端點之間具有多條通路,這就是SCTP 關(guān)聯(lián)的多地址性。SCTP 關(guān)聯(lián)的多地址性是 SCTP 與TCP 最大的不同。
一個關(guān)聯(lián)可以包括多條通路,但只有一個首選通路讶踪。如圖1所示廓俭,MGC(如 GTSOFTX3000)一個端點包括兩個傳送地址(10.11.23.14:2905 和10.11.23.15: 2905),而SG 一個端點也包括兩個傳送地址(10.11.23.16:2904 和10.11.23.17: 2904)咬腕。
圖2 SCTP 雙歸屬
此兩個端點決定了一個關(guān)聯(lián)凝危,該關(guān)聯(lián)包括4 條通路(Path0、Path1晨逝、Path2 和Path3)蛾默。 根據(jù)數(shù)據(jù)配置可以確定此4 條通路的選擇方式,如圖2所示捉貌。圖中定義了4 條通 路支鸡,而且首選通路為Path0: Path0:本端傳送地址1(10.11.23.14:2905)發(fā)送SCTP 分組到對端傳送地 址1(10.11.23.16:2904)。
Path1:本端傳送地址1(10.11.23.14:2905)發(fā)送SCTP 分組到對端傳送地 址2(10.11.23.17:2904)趁窃。
Path2:本端傳送地址2(10.11.23.15:2905)發(fā)送SCTP 分組到對端傳送地 址1(10.11.23.16:2904)牧挣。
Path3:本端傳送地址2(10.11.23.15:2905)發(fā)送SCTP 分組到對端傳送地 址2(10.11.23.17:2904)。
端點發(fā)送的 SCTP 工作原理為:本端點傳送地址A 發(fā)送的SCTP 包通過首選通路發(fā) 送到對端端點醒陆。當(dāng)首選通路出現(xiàn)故障后瀑构,SCTP 可以自動切換到其他備用通路上, 優(yōu)先切換對端端點的傳送地址刨摩,再次切換本端端點的傳送地址寺晌。
SCTP 定義了心跳消息(Heart Beat)世吨。當(dāng)某條通路空閑時,本端SCTP 用戶要求 SCTP 生成相應(yīng)的心跳消息并通過該通路發(fā)送到對端端點呻征,而對端端點必須立即發(fā) 回對應(yīng)的心跳確認(rèn)消息耘婚。這種機(jī)制被用來精確測量回路時延RTT(Round Trip Time),而且可以隨時監(jiān)視關(guān)聯(lián)的可用情況和保持SCTP 關(guān)聯(lián)的激活狀態(tài)陆赋。
圖3 確定通路選擇方式的數(shù)據(jù)配置
TSN 和SSN
傳輸順序號 TSN(Transmission Sequence Number)
SCTP 使用TSN 機(jī)制實現(xiàn)數(shù)據(jù)的確認(rèn)傳輸沐祷。一個關(guān)聯(lián)的一端為本端發(fā)送的每個數(shù)據(jù) 塊順序分配一個基于初始TSN 的32 位順序號,以便對端收到時進(jìn)行確認(rèn)攒岛。 TSN 是基于關(guān)聯(lián)進(jìn)行維護(hù)的赖临。
流順序號 SSN(Stream Sequence Number)
SCTP 為本端在這個流中發(fā)送的每個數(shù)據(jù)塊順序分配一個16 位SSN,以便保證流 內(nèi)的順序傳遞灾锯。 在關(guān)聯(lián)建立時兢榨,所有流中的SSN 都是從0 開始。當(dāng)SSN 到達(dá)65535 后挠进,則接下來 的SSN 為0色乾。 TSN 和SSN 的分配是相互獨立的。
擁塞窗口CWND(Congestion Window)
SCTP 也是一個滑動窗口協(xié)議领突,擁塞窗口是針對每個目的地址維護(hù)的暖璧,它會根據(jù)網(wǎng) 絡(luò)狀況調(diào)節(jié)。當(dāng)目的地址的發(fā)送未證實消息長度超過其CWND 時君旦,端點將停止向這 個地址發(fā)送數(shù)據(jù)澎办。
接收窗口RWND(Receive Window)
RWND 用來描述一個關(guān)聯(lián)對端的接收緩沖區(qū)大小。關(guān)聯(lián)建立過程中金砍,雙方會交換彼 此的初始RWND局蚀。RWND 會根據(jù)數(shù)據(jù)發(fā)送、證實的情況即時地變化恕稠。RWND 的大 小限制了SCTP 可以發(fā)送的數(shù)據(jù)的大小琅绅。當(dāng)RWND 等于0 時,SCTP 還可以發(fā)送一 個數(shù)據(jù)報鹅巍,以便通過證實消息得知對方緩沖區(qū)的變化千扶,直到達(dá)到CWND 的限制。
傳輸控制塊TCB(Transmission Control Block)
TCB 是一種內(nèi)部數(shù)據(jù)結(jié)構(gòu)骆捧,是一個SCTP 端點為它與其他端點之間已經(jīng)啟動的每一 個關(guān)聯(lián)生成的澎羞。TCB 包括端點的所有狀態(tài)、操作信息敛苇,便于維護(hù)和管理相應(yīng)的關(guān)聯(lián)妆绞。
功能
與傳統(tǒng)傳輸層協(xié)議相比,SCTP 的兩個最重要的增強(qiáng)功能是端宿多宿主和多流功能。
多宿主
多宿主為應(yīng)用程序提供比使用 TCP 的應(yīng)用程序更高的可用性括饶。多宿主主機(jī)是具有多個網(wǎng)絡(luò)接口株茶,因此可以尋址的多個 IP 地址的主機(jī)。在 TCP 中巷帝,連接是指兩個端點之間的通道(在這種情況下忌卤,是兩個主機(jī)接口之間的套接字)扫夜。SCTP 引入了存在于兩個主機(jī)之間的關(guān)聯(lián)的概念楞泼,但可能與每個主機(jī)的多個接口協(xié)作。
圖4.TCP 連接與 SCTP 關(guān)聯(lián)
頂部是 TCP 連接笤闯。每個主機(jī)包括一個網(wǎng)絡(luò)接口;在每個客戶端和服務(wù)器上的單個接口之間創(chuàng)建連接堕阔。建立后,連接綁定到每個接口颗味。
在圖的底部超陆,您可以看到一個包含每個主機(jī)兩個網(wǎng)絡(luò)接口的體系結(jié)構(gòu)。通過獨立網(wǎng)絡(luò)提供兩條路徑浦马,一條從接口 C0 到 S0时呀,另一條從 C1 到 S1。在 SCTP 中晶默,這兩個路徑將收集到關(guān)聯(lián)中谨娜。
SCTP 使用內(nèi)置檢測信號監(jiān)視關(guān)聯(lián)路徑;檢測到路徑故障時,協(xié)議通過備用路徑發(fā)送流量磺陡。應(yīng)用程序甚至不需要知道發(fā)生了故障轉(zhuǎn)移恢復(fù)趴梢。
故障轉(zhuǎn)移還可用于維護(hù)網(wǎng)絡(luò)應(yīng)用程序連接。例如币他,考慮包含無線 802.11 接口和以太網(wǎng)接口的筆記本電腦坞靶。當(dāng)筆記本電腦位于其塢站中時,將首選高速以太網(wǎng)接口(在 SCTP 中蝴悉,稱為主地址);但在此連接丟失(從塢站中刪除)后彰阴,連接將故障通過無線接口。返回塢站后拍冠,將檢測到以太網(wǎng)連接尿这,并在此接口上恢復(fù)通信。這是一種強(qiáng)大的機(jī)制倦微,用于提供高可用性和更高的可靠性妻味。
多流
在某些方面,SCTP 關(guān)聯(lián)就像 TCP 連接欣福,只是 SCTP 支持關(guān)聯(lián)中的多個流责球。關(guān)聯(lián)中的所有流都是獨立的,但與關(guān)聯(lián)相關(guān)。
圖5.SCTP 關(guān)聯(lián)與流的關(guān)系
每個流都得到一個流號雏逾,該流號在流經(jīng)關(guān)聯(lián)流的 SCTP 數(shù)據(jù)包中編碼嘉裤。多流很重要,因為阻塞的流(例如栖博,由于數(shù)據(jù)包丟失而等待重新傳輸?shù)牧鳎┎粫绊戧P(guān)聯(lián)中的其他流屑宠。此問題通常稱為線頭阻塞。TCP 容易出現(xiàn)這種阻塞仇让。
多個流如何在傳輸數(shù)據(jù)時提供更好的響應(yīng)能力典奉?例如,HTTP 協(xié)議在同一套接字上共享控制和數(shù)據(jù)丧叽。Web 客戶端從服務(wù)器請求文件卫玖,服務(wù)器通過同一連接發(fā)送文件。多流 HTTP 服務(wù)器將提供更好的交互性踊淳,因為可以在關(guān)聯(lián)中的獨立流上處理多個請求假瞬。此功能將并行化響應(yīng),雖然速度可能更快迂尝,但同時加載 HTML 和圖形圖像脱茉,從而提供更好的響應(yīng)能力。
多流是SCTP的一個重要功能垄开,尤其是當(dāng)你在協(xié)議設(shè)計中考慮一些控制和數(shù)據(jù)問題時琴许。在 TCP 中,控制和數(shù)據(jù)通常共享相同的連接说榆,這可能有問題虚吟,因為控制數(shù)據(jù)包可能會延遲在數(shù)據(jù)包后面。如果將控制和數(shù)據(jù)拆分為獨立的流签财,就可以更及時地處理控制數(shù)據(jù)串慰,從而更好地利用可用資源。
啟動保護(hù)
在 TCP 和 SCTP 中啟動新連接時唱蒸,數(shù)據(jù)包握手將發(fā)生邦鲫。在 TCP 中,它稱為三向握手神汹。客戶端發(fā)送一個數(shù)據(jù)包(用于同步的短)庆捺,服務(wù)器會響應(yīng)該數(shù)據(jù)包(同步確認(rèn))。最后屁魏,客戶端用數(shù)據(jù)包確認(rèn)接收(參見圖 6)滔以。SYN``SYN-ACK``ACK
圖6.TCP 和 STCP 握手的數(shù)據(jù)包交換
TCP 可能發(fā)生的問題是,當(dāng)惡意客戶端使用虛假源地址偽造 IP 數(shù)據(jù)包氓拼,然后用 TCP 數(shù)據(jù)包充用服務(wù)器時你画。服務(wù)器在收到 時為連接分配資源抵碟,然后在數(shù)據(jù)包洪流下,最終將用完坏匪,無法為新請求提供服務(wù)拟逮。這稱為拒絕服務(wù)(DoS) 攻擊。SYN``SYN``SYN
SCTP 通過四向握手和引入 Cookie 來防止此類攻擊适滓。在 SCTP 中敦迄,客戶端啟動與數(shù)據(jù)包的連接。服務(wù)器響應(yīng) 的 包含 Cookie(標(biāo)識此建議連接的唯一上下文)凭迹。然后罚屋,客戶端使用 響應(yīng),其中包含服務(wù)器發(fā)送的 Cookie蕊苗。此時沿后,服務(wù)器為連接分配資源沿彭,并通過向客戶端發(fā)送 一個來確認(rèn)這一點朽砰。INIT``INIT-ACK``COOKIE-ECHO``COOKIE-ACK
為了解決使用四向握手延遲數(shù)據(jù)移動的問題,SCTP 允許將數(shù)據(jù)包含在 和 數(shù)據(jù)包中喉刘。COOKIE-ECHO``COOKIE-ACK
消息框架
使用消息框架時瞧柔,將保留通過套接字傳遞消息的邊界;這意味著,如果客戶端向服務(wù)器發(fā)送 100 個字節(jié)睦裳,后跟 50 個字節(jié)造锅,則服務(wù)器將分別讀取 100 字節(jié)和 50 字節(jié),用于兩次讀取廉邑。UDP 也以這種方式運行哥蔚,這使得它有利于面向消息的協(xié)議。
相比之下蛛蒙,TCP 以字節(jié)流方式運行糙箍。如果沒有框架,對等體可能會收到比發(fā)送的多或少(拆分寫入或?qū)⒍鄠€寫入聚合到一次讀取中)牵祟。此行為要求通過 TCP 運行的面向消息的協(xié)議在其應(yīng)用程序?qū)樱ㄒ豁棟撛诘膹?fù)雜任務(wù))中提供數(shù)據(jù)緩沖區(qū)和消息框架深夯。
SCTP 在數(shù)據(jù)傳輸中提供消息框架。當(dāng)對等體對套接字執(zhí)行寫入時诺苹,可以保證在對等端點讀取此大小相同的數(shù)據(jù)塊咕晋。
圖7.UDP/SCTP 中的消息框架與面向字節(jié)流的協(xié)議
用戶數(shù)據(jù)分段
SCTP 通過對傳送通路上最大PMTU(Path Maximum TransmissiON Unit)的檢測, 實現(xiàn)在SCTP 層將超大用戶數(shù)據(jù)分片打包收奔,避免在IP 層的多次分片掌呜、重組,可以減 少IP 層的數(shù)據(jù)負(fù)擔(dān)坪哄。
在發(fā)送端质蕉,SCTP 可以對大的用戶數(shù)據(jù)報進(jìn)行分片以確保SCTP 數(shù)據(jù)報傳遞到 低層時適合通路MTU(Maximum Transmission Unit)呢撞。
在接收端,SCTP 將分片重組為完整的用戶數(shù)據(jù)報饰剥,然后傳遞給SCTP 用戶殊霞。
證實和避免擁塞
證實和重傳是協(xié)議保證傳輸可靠性的策略,SCTP 也一樣汰蓉。證實機(jī)制是SCTP 保證 傳輸可靠性的基石绷蹲。避免擁塞沿襲了TCP 的窗口機(jī)制,進(jìn)行合適的流量控制顾孽。
SCTP 在將數(shù)據(jù)(數(shù)據(jù)分片或未分片的用戶數(shù)據(jù)報)發(fā)送給底層之前順序地為 之分配一個發(fā)送順序號(TSN)祝钢。TSN 和SSN(流順序號)是相互獨立的,TSN 用于保證傳輸?shù)目煽啃匀艉瘢琒SN 用于保證流內(nèi)消息的順序傳遞拦英。TSN 和SSN 在功能上使可靠傳遞和順序傳遞分開。接收端證實所有收到的 TSNs测秸,即使其中有些尚未收到疤估。包重發(fā)功能負(fù)責(zé) TSN 的證實,還負(fù)責(zé)擁塞消除霎冯。
消息塊綁定
如果長度很短的用戶數(shù)據(jù)被帶上很大一個 SCTP 消息頭铃拇,其傳遞效率會很低,因此沈撞, SCTP 將幾個用戶數(shù)據(jù)綁定在一個SCTP 報文里面?zhèn)鬏斂独螅蕴岣邘挼睦寐省?/p>
SCTP 分組由公共分組頭和一個/多個信息塊組成,信息塊可以是用戶數(shù)據(jù)缠俺,也 可以是SCTP 控制信息显晶。
SCTP 用戶能夠可選地使用捆綁功能,決定是否將多個用戶數(shù)據(jù)報捆綁在一個 SCTP 分組中壹士。
為提高效率磷雇,擁塞/重發(fā)時,捆綁功能可能仍被執(zhí)行墓卦,即使用戶已經(jīng)禁止捆綁倦春。
分組的有效性
分組的有效性是 SCTP 提供無差錯傳輸?shù)幕CTP 分組的公共分組頭包含一個 驗證標(biāo)簽(VerificATIon Tag)和一個可選的32 位校驗碼(Checksum)落剪。 驗證標(biāo)簽的值由關(guān)聯(lián)兩端在關(guān)聯(lián)啟動時選擇睁本。如果收到的分組中如果沒有期望的驗 證標(biāo)簽值,接收端將丟棄這個分組忠怖,以阻止攻擊和失效的SCTP 分組呢堰。 校驗碼由 SCTP 分組的發(fā)送方設(shè)置,以提供附加的保護(hù)凡泣,用來避免由網(wǎng)絡(luò)造成的數(shù) 據(jù)差錯枉疼。接收端將丟棄包含無效校驗碼的SCTP 分組皮假。
可配置無需交付
SCTP 中的消息傳輸可靠,但不一定按所需順序傳輸骂维。TCP 保證數(shù)據(jù)按順序傳遞(考慮到 TCP 是流協(xié)議惹资,這是一件好事)。但是航闺,您也可以在 SCTP 中配置流以根據(jù)需要接受無序消息褪测。
此功能在面向消息的協(xié)議中非常有用,在該協(xié)議中潦刃,請求是獨立的侮措,排序并不重要。此外乖杠,您可以在關(guān)聯(lián)中按流配置無序傳遞分扎。
優(yōu)雅關(guān)閉
TCP 和 SCTP 是基于連接的協(xié)議,而 UDP 是無連接協(xié)議胧洒。TCP 和 SCTP 都需要連接設(shè)置和對等體之間的拆解畏吓。在SCTP中,套接字關(guān)閉的不同情況是TCP的半關(guān)閉的刪除略荡。
圖8.TCP 和 SCTP 連接終止序列
在 TCP 中庵佣,對等體可以關(guān)閉其套接字的末尾(導(dǎo)致發(fā)送數(shù)據(jù)包),但隨后可以繼續(xù)接收數(shù)據(jù)汛兜。表示此終結(jié)點不再發(fā)送數(shù)據(jù),但直到對等體關(guān)閉套接字的末尾通今,它才能繼續(xù)傳輸數(shù)據(jù)粥谬。應(yīng)用程序很少使用此半封閉狀態(tài),因此 SCTP 設(shè)計人員選擇將其刪除辫塌,并將其替換為更簡潔的終止序列漏策。當(dāng)對等體關(guān)閉其套接字(導(dǎo)致發(fā)出基元)時,需要關(guān)閉兩個終結(jié)點臼氨,并且不允許在任一方向上進(jìn)一步移動數(shù)據(jù)掺喻。FIN``FIN``SHUTDOWN
分組管理
發(fā)送端的 SCTP 用戶能夠使用一組傳送地址作為SCTP 分組的目的地。SCTP 管理 功能可以根據(jù)SCTP 用戶的指令和當(dāng)前合格的目的地集合的可達(dá)性狀態(tài)储矩,為每個發(fā) 送的SCTP 分組選擇一個目的地傳送地址感耙。當(dāng)其他分組業(yè)務(wù)量不能完全表明可達(dá)性 時,通路管理功能可以通過心跳消息來監(jiān)視到某個目的地地址的可達(dá)性持隧,并當(dāng)任何 對端傳送地址的可達(dá)性發(fā)生變化時即硼,向SCTP 用戶提供指示。通路功能也用來在偶 聯(lián)建立時屡拨,向?qū)Χ藞蟾婧细竦谋径藗魉偷刂芳现凰郑褟膶Χ朔祷氐膫魉偷刂穲蟾?給本地的SCTP 用戶褥实。 在關(guān)聯(lián)建立時,為每個 SCTP 端點定義一個首選通路裂允,用來正常情況下發(fā)送SCTP 分組损离。
基本信令流程
關(guān)聯(lián)的建立和發(fā)送流程
SCTP 端點A 啟動建立關(guān)聯(lián),并向端點B 發(fā)送一個用戶消息绝编,隨后端點B 向A 發(fā)送 兩個用戶消息草冈。(假定這些消息沒有捆綁和分段)。信令流程如圖1所示瓮增。
圖9 關(guān)聯(lián)建立過程消息交互圖
- 端點A 創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu)TCB(傳輸控制塊)來描述即將發(fā)起的這個關(guān)聯(lián)(包 含關(guān)聯(lián)的基本信息)怎棱,然后向端點B 發(fā)送INIT 數(shù)據(jù)塊。INIT 數(shù)據(jù)塊中主要包 括如下參數(shù):
- 啟動標(biāo)簽(Initiate Tag):對端驗證標(biāo)簽绷跑,如設(shè)為Tag_A拳恋。Tag_A 是從1 到 4294967295 中的一個隨機(jī)數(shù)。
- 輸出流數(shù)量(OS):本端點期望的最大出局流的數(shù)量砸捏。
- 輸入流數(shù)量(MIS):本端點允許入局流的最大數(shù)量谬运。
- 端點B 收到INIT 消息后,立即用INIT ACK 數(shù)據(jù)塊響應(yīng)垦藏。INIT ACK 數(shù)據(jù)塊中 必須帶有如下參數(shù):
- 目的地 IP 地址:設(shè)置成INIT 數(shù)據(jù)塊的起源IP 地址梆暖。
- 啟動標(biāo)簽(Initiate Tag):設(shè)置成Tag_B。
- 狀態(tài) COOKIE(STATE COOKIE):根據(jù)關(guān)聯(lián)的基本信息生成一個TCB掂骏,不 過這個TCB 是一個臨時TCB轰驳。這個TCB 生成以后,將其中的必要信息(包含 一個COOKIE 生成的時間戳弟灼、COOKIE 的生命期)和一個本端的密鑰通過 RFC2401 描述的算法計算成一個32 位的摘要MAC(這種計算是不可逆的)级解。 必要信息和MAC 組合成STATE COOKIE 參數(shù)。
- 本端點傳送地址田绑。
- 最大入局流的數(shù)量勤哗。
- 最大出局流的數(shù)量。
- 端點A 收到INIT ACK 后掩驱,首先停止INIT 定時器離開COOKIE-WAIT 狀態(tài)芒划, 然后發(fā)送COOKIE ECHO 數(shù)據(jù)塊,將收到INIT ACK 數(shù)據(jù)塊中的STATE COOKIE 參數(shù)原封帶回欧穴。最后端點A 啟動COOKIE 定時器并進(jìn)入 COOKIE-ECHOED 狀態(tài)民逼。
- 端點B收到COOKIE ECHO數(shù)據(jù)塊后,進(jìn)行COOKIE驗證苔可。將STATE COOKIE 中的TCB 部分和本端密鑰根據(jù)RFC2401 的MAC 算法進(jìn)行計算缴挖,得出的MAC 和STATE COOKIE 中攜帶的MAC 進(jìn)行比較。如果不同則丟棄這個消息焚辅;如 果相同映屋,則取出TCB 部分的時間戳苟鸯,和當(dāng)前時間比較,看時間是否已經(jīng)超過 了COOKIE 的生命期棚点。如果是早处,同樣丟棄。否則根據(jù)TCB 中的信息建立一個 和端A 的關(guān)聯(lián)瘫析。端點B 將狀態(tài)遷入ESTABLISHED砌梆,并發(fā)出COOKIE ACK 數(shù) 據(jù)塊。端點B 向SCTP 用戶發(fā)送SCOMMUNCIATION UP 通知贬循。
- 端點A 向端點B 發(fā)送一個DATA 數(shù)據(jù)塊咸包,啟動T3-RTS 定時器。DATA 數(shù)據(jù) 塊中必須帶有如下參數(shù):
- TSN:DATA 數(shù)據(jù)塊的初始TSN杖虾。
- 流標(biāo)識符(Stream Identifier):用戶數(shù)據(jù)屬于的流烂瘫,假設(shè)流標(biāo)識符為0。
- 流順序碼(Stream Sequence Number):所在流中的用戶數(shù)據(jù)的順序號碼奇适。 該字段從0 到65535坟比。
- 用戶數(shù)據(jù)(User Data):攜帶用戶數(shù)據(jù)凈荷。
- 端點B 收到DATA 數(shù)據(jù)塊后嚷往,返回SACK 數(shù)據(jù)塊葛账。SACK 數(shù)據(jù)塊中必須帶有 如下參數(shù):
- 累積證實 TSN 標(biāo)簽(Cumulative TSN Ack):端點A 的初始TSN。
- 間隔塊(Gap Ack Block):此值為0皮仁。 端點 A 收到SACK 數(shù)據(jù)塊后籍琳,停止T3-RTX 定時器。
- 端點B 向端點A 發(fā)送第一個DATA 數(shù)據(jù)塊魂贬。DATA 數(shù)據(jù)塊中必須帶有如下參 數(shù):
- TSN:端點B 發(fā)出DATA 數(shù)據(jù)塊的初始TSN巩割。
- 流標(biāo)識符(Stream Identifier):用戶數(shù)據(jù)屬于的流,假設(shè)流標(biāo)識符為0付燥。
- 流順序碼(Stream Sequence Number):所在流中的用戶數(shù)據(jù)的順序號碼。 假設(shè)流順序碼為0愈犹。
- 用戶數(shù)據(jù)(User Data):攜帶用戶數(shù)據(jù)凈荷键科。
- 端點B 向端點A 發(fā)送第二個DATA 數(shù)據(jù)塊。DATA 數(shù)據(jù)塊中必須帶有如下參 數(shù):
- TSN:端點B 發(fā)出DATA 數(shù)據(jù)塊的初始TSN+1漩怎。
- 流標(biāo)識符(Stream Identifier):用戶數(shù)據(jù)屬于的流勋颖,假設(shè)流標(biāo)識符為0。
- 流順序碼(Stream Sequence Number):所在流中的用戶數(shù)據(jù)的順序號碼勋锤。 此時流順序碼為1饭玲。
- 用戶數(shù)據(jù)(User Data):攜帶用戶數(shù)據(jù)凈荷。
- 端點A 收到DATA 數(shù)據(jù)塊后叁执,返回SACK 數(shù)據(jù)塊茄厘。SACK 數(shù)據(jù)塊中必須帶有 如下參數(shù):
- 累積證實 TSN 標(biāo)簽(Cumulative TSN Ack):端點B 的初始TSN矮冬。
- 間隔塊(Gap Ack Block):此值為0。
關(guān)聯(lián)關(guān)閉流程
一個端點退出服務(wù)時次哈,需要停止它的關(guān)聯(lián)。關(guān)聯(lián)的停止使用兩種流程:關(guān)聯(lián)的中止 流程(非正常關(guān)閉)和關(guān)聯(lián)的正常關(guān)閉流程窑滞。 關(guān)聯(lián)的中止(非正常關(guān)閉)可以在任何未完成期間進(jìn)行哀卫,關(guān)聯(lián)的兩端都舍棄數(shù)據(jù)并 且不提交到對端巨坊。此種方法不考慮數(shù)據(jù)的安全。關(guān)聯(lián)的中止步驟比較簡單:發(fā)起端 點向?qū)Χ硕它c發(fā)送ABORT 數(shù)據(jù)塊趾撵,發(fā)送的SCTP 分組中必須填上對端端點的驗證 標(biāo)簽带斑,而且不在ABORT 數(shù)據(jù)塊中捆綁任何DATA 數(shù)據(jù)鼓寺;接收端點收到ABORT 數(shù) 據(jù)塊后,進(jìn)行驗證標(biāo)簽的檢查勋磕。如果驗證標(biāo)簽與本端驗證標(biāo)簽相同,接收端點從記 錄上清除該關(guān)聯(lián)苦银,并向SCTP 用戶報告關(guān)聯(lián)的停止赶站。
關(guān)聯(lián)的正常關(guān)閉:任何一個端點執(zhí)行正常關(guān)閉程序時,關(guān)聯(lián)的兩端將停止接受從其 SCTP 用戶發(fā)來的新數(shù)據(jù)想括,并且在發(fā)送或接收到SHUTDOWN 數(shù)據(jù)塊時烙博,把分組中 的數(shù)據(jù)遞交給SCTP 用戶。關(guān)聯(lián)的關(guān)閉可以保證所有兩端的未發(fā)送铺根、發(fā)送未證實數(shù) 據(jù)得到發(fā)送和證實后再終止關(guān)聯(lián)乔宿。
圖10 關(guān)聯(lián)正常關(guān)閉消息交互圖
關(guān)聯(lián)的正常關(guān)閉步驟如下:
- 關(guān)聯(lián)關(guān)閉發(fā)起端點A 的SCTP 用戶向SCTP 發(fā)送請求SHUTDOWN 原因。 SCTP 關(guān)聯(lián)從ESTABLISHED 狀態(tài)遷入SHUTDOWN-PENDING 狀態(tài)掂林。在這 個狀態(tài)党饮,SCTP 不接受SCTP 用戶在這個關(guān)聯(lián)上的任何數(shù)據(jù)發(fā)送請求。同時等待端點A 所有發(fā)送未證實的數(shù)據(jù)得到端點B 的證實氯窍。當(dāng)所有端點A 發(fā)送未證 實數(shù)據(jù)得到證實蹲堂,則向端點B 發(fā)送SHUTDOWN 數(shù)據(jù)塊。端點A 啟動 T2-shutdown 定時器進(jìn)入SHUTDOWN-SENT 狀態(tài)政供。啟動T2-shutdown 定時 器的目的是等待端點B 發(fā)回的SHUTDOWN-ACK 數(shù)據(jù)塊朽基,如果定時器超時, 則端點A 必須重新發(fā)送SHUTDOWN 數(shù)據(jù)塊衅檀。
- 端點B 收到SHUTDOWN 消息后霎俩,進(jìn)入SHOUTDOWN-RECEIVED 狀態(tài)打却, 不再接收從SCTP 用戶發(fā)來的的新數(shù)據(jù),并且檢查數(shù)據(jù)塊的累積TSN ACK 字 段柳击,驗證所有未完成的DATA 數(shù)據(jù)塊已經(jīng)被SHUTDOWN 的發(fā)送方接收。當(dāng) 端點B 所有未發(fā)送數(shù)據(jù)和發(fā)送未證實數(shù)據(jù)得到發(fā)送和證實后彤守, 發(fā)送 SHUTDOWN ACK 數(shù)據(jù)塊并啟動本端T2-SHUTDOWN 定時器,并且進(jìn)入 SHUTDOWN-ACK-SENT 狀態(tài)侈离。如果定時器超時了,端點B 則重新發(fā)送 SHUTDOWN ACK 數(shù)據(jù)塊铺坞。
- 端點A 收到SHUTDOWN ACK 消息后,停止T2-shutdown 定時器坯沪,并且向端 點B 發(fā)送SHUTDOWN COMPLETE 數(shù)據(jù)塊擒滑,并清除關(guān)聯(lián)的所有記錄丐一。端點B 收到SHUTDOWN COMPLETE 數(shù)據(jù)塊后, 驗證是否處于 SHUTDOWN-ACK-SENT 狀態(tài)巨柒。如果不是處于該狀態(tài)柠衍,則丟棄該數(shù)據(jù)塊;如 果端點處于SHUTDOWN-ACK-SENT 狀態(tài)牺勾,端點B 則停止T2-shutdown 定時 器并清除關(guān)聯(lián)的所有記錄垫蛆,進(jìn)入CLOSED 狀態(tài)袱饭。
示例
本文提供了一個用 C 編程語言編寫的示例服務(wù)器和客戶端,并演示 SCTP 的多流功能懦趋。此示例演示實現(xiàn)SCTP協(xié)議形式的服務(wù)器疹味。此傳統(tǒng)服務(wù)器將當(dāng)前時間發(fā)出到連接的客戶端糙捺,但對于 SCTP,我發(fā)出流 0 上的本地時間和流 1 上的格林威治標(biāo)準(zhǔn)時間 (GMT)坎缭。這個簡單的示例允許我演示流通信的 API。
![image](https://upload-images.jianshu.io/upload_images/2844443-0bd6491c9fe45314.gif?imageMogr2/auto-orient/strip "image")
圖11.多流服務(wù)器和客戶端中使用的套接字功能
這些應(yīng)用程序是在具有 2.6.11 內(nèi)核和 Linux 內(nèi)核 SCTP 項目 (lksctp) 的 GNU/Linux 操作系統(tǒng)上開發(fā)的坏快。
服務(wù)端
int main()
{
int listenSock, connSock, ret;
struct sockaddr_in servaddr;
char buffer[MAX_BUFFER+1];
time_t currentTime;
/* Create SCTP TCP-Style Socket */
listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
/* Accept connections from any interface */
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons(MY_PORT_NUM);
/* Bind to the wildcard address (all) and MY_PORT_NUM */
ret = bind( listenSock,
(struct sockaddr *)&servaddr, sizeof(servaddr) );
/* Place the server socket into the listening state */
listen( listenSock, 5 );
/* Server loop... */
while( 1 ) {
/* Await a new client connection */
connSock = accept( listenSock,
(struct sockaddr *)NULL, (int *)NULL );
/* New client socket has connected */
/* Grab the current time */
currentTime = time(NULL);
/* Send local time on stream 0 (local time stream) */
snprintf( buffer, MAX_BUFFER, "%s\n", ctime(¤tTime) );
ret = sctp_sendmsg( connSock,
(void *)buffer, (size_t)strlen(buffer),
NULL, 0, 0, 0, LOCALTIME_STREAM, 0, 0 );
/* Send GMT on stream 1 (GMT stream) */
snprintf( buffer, MAX_BUFFER, "%s\n",
asctime( gmtime( ¤tTime ) ) );
ret = sctp_sendmsg( connSock,
(void *)buffer, (size_t)strlen(buffer),
NULL, 0, 0, 0, GMT_STREAM, 0, 0 );
/* Close the client connection */
close( connSock );
}
return 0;
}
首先創(chuàng)建服務(wù)器套接字,允許從任何本地接口(使用通配符地址)進(jìn)行連接拾给。將此描述符綁定到套接字鸣戴,然后將服務(wù)器套接字放置到偵聽狀態(tài)。此時创千,傳入連接是可以被接收的入偷。IPPROTO_SCTP``sockaddr``INADDR_ANY``sockaddr``bind
請注意疏之,SCTP 使用許多與 TCP 和 UDP 相同的套接字 API。
服務(wù)端循環(huán)等待新的客戶端連接丙曙。從函數(shù)返回后其骄,套接字將標(biāo)識新的客戶端連接拯爽。接著使用函數(shù)獲取當(dāng)前時間,然后將其轉(zhuǎn)換為特定的字符串毯炮。使用函數(shù)(非標(biāo)準(zhǔn)套接字調(diào)用)桃煎,可以將字符串發(fā)送到客戶端,指定特定的流 ()洲拇。發(fā)送本地時間字符串后,我在 GMT 中將當(dāng)前時間打包為字符串,然后在流上發(fā)送此時間纽乱。accept``connSock``time``snprintf``sctp_sendmsg``LOCALTIME_STREAM``GMT_STREAM
至此服務(wù)器已完成其職責(zé),因此關(guān)閉套接字并等待新的客戶端連接薯嗤。
客戶端
int main()
{
int connSock, in, i, flags;
struct sockaddr_in servaddr;
struct sctp_sndrcvinfo sndrcvinfo;
struct sctp_event_subscribe events;
char buffer[MAX_BUFFER+1];
/* Create an SCTP TCP-Style Socket */
connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
/* Specify the peer endpoint to which we'll connect */
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MY_PORT_NUM);
servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
/* Connect to the server */
connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
/* Enable receipt of SCTP Snd/Rcv Data via sctp_recvmsg */
memset( (void *)&events, 0, sizeof(events) );
events.sctp_data_io_event = 1;
setsockopt( connSock, SOL_SCTP, SCTP_EVENTS,
(const void *)&events, sizeof(events) );
/* Expect two messages from the peer */
for (i = 0 ; i < 2 ; i++) {
in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer),
(struct sockaddr *)NULL, 0,
&sndrcvinfo, &flags );
/* Null terminate the incoming string */
buffer[in] = 0;
if (sndrcvinfo.sinfo_stream == LOCALTIME_STREAM) {
printf("(Local) %s\n", buffer);
} else if (sndrcvinfo.sinfo_stream == GMT_STREAM) {
printf("(GMT ) %s\n", buffer);
}
}
/* Close our socket and exit */
close(connSock);
return 0;
}
SCTP的未來
SCTP 是一個相對較新的協(xié)議骆姐,因為它在 2000 年 10 月成為 RFC捏题。自那時起公荧,它進(jìn)入所有主要操作系統(tǒng),包括GNU/Linux窟社、BSD和S solaris和windows绪钥。
除了可用性,應(yīng)用程序還將開始使用 SCTP 作為其主要傳輸钠四。FTP 和 HTTP 等傳統(tǒng)應(yīng)用程序是基于 SCTP 的功能構(gòu)建的缀去。其他協(xié)議正在使用 SCTP甸祭,例如會話啟動協(xié)議 (SIP) 和通用信道信令系統(tǒng) 7 號 (SS7)池户。在商業(yè)上凡怎,您可以在思科的 IOS 中找到 SCTP赊抖。
隨著SCTP加入2.6 Linux內(nèi)核氛雪,現(xiàn)在可以構(gòu)建和部署高可用和可靠的網(wǎng)絡(luò)應(yīng)用程序。作為基于 IP 的協(xié)議浴鸿,SCTP 是 TCP 和 UDP 的無縫替代弦追,但也擴(kuò)展了新服務(wù)劲件,如多宿主、多流和更高的安全性。現(xiàn)在您已經(jīng)看到了SCTP的一些高級功能延刘,請?zhí)剿魉钠渌δ堋inux 內(nèi)核 SCTP 項目 (lksctp) 提供 API 擴(kuò)展和文檔,可幫助您在路上。