摘要:狀態(tài)碼當(dāng)關(guān)閉一個(gè)連接時(shí)如在開始握手已經(jīng)完成后,發(fā)送一個(gè)關(guān)閉幀,終端可能會(huì)說明關(guān)閉的原因。表示終端由于協(xié)議錯(cuò)誤中止了連接。這個(gè)狀態(tài)碼是為了給上層應(yīng)用表示連接被異常關(guān)閉如沒有發(fā)送或者接受一個(gè)關(guān)閉幀這種場(chǎng)景的使用而設(shè)計(jì)的。
概述
本文為 WebSocket 協(xié)議的第七章,本文翻譯的主要內(nèi)容為 WebSocket 連接關(guān)閉相關(guān)內(nèi)容。
關(guān)閉連接(協(xié)議正文) 7.1 定義 7.1.1 關(guān)閉 WebSocket 連接要關(guān)閉 WebSocket 連接,終端需要關(guān)閉底層的 TCP 連接。終端需要使用一個(gè)方法來干凈的關(guān)閉TCP連接,還有 TLS 會(huì)話,如果可能的話,拋棄后面可能受到的任意字符。終端可能會(huì)在需要的時(shí)候,通過任何方式來關(guān)閉連接,例如在收到攻擊時(shí)。
在底層的 TCP 連接中,通常大多數(shù)情況下,服務(wù)端應(yīng)該先關(guān)閉,所以是服務(wù)端而不是客戶端保持 TIME_WAIT 狀態(tài)(因?yàn)榭蛻舳讼汝P(guān)閉的話,這會(huì)阻止服務(wù)端在2 MSL 內(nèi)重新打開這條連接,而如果服務(wù)器處于 TIME_WAIT 狀態(tài)下,如果收到了一個(gè)帶有更大序列號(hào)的新的 SYN 包時(shí),也能夠立即響應(yīng)重新打開連接,從而不會(huì)對(duì)服務(wù)器產(chǎn)生影響)。反常情況(例如在合理的時(shí)間后,服務(wù)端收到一個(gè) TCP 關(guān)閉包)下,客戶端應(yīng)該開始關(guān)閉 TCP 連接。像這樣的,當(dāng)服務(wù)端進(jìn)入關(guān)閉 WebSocket 連接狀態(tài)時(shí),它應(yīng)該立刻準(zhǔn)備關(guān)閉 TCP 連接,然后當(dāng)客戶端客戶端準(zhǔn)備關(guān)閉連接時(shí),他應(yīng)該等待服務(wù)端的 TCP 關(guān)閉包。
用 C 語(yǔ)言的 Berkeley socket 作為例子來展示如何徹底的關(guān)閉連接,一端需要用 SHUP_WR 調(diào)用 shutdown() 方法,調(diào)用 recv() 直到獲得一個(gè)值為 0 的表示對(duì)面也準(zhǔn)備有序關(guān)閉連接的返回值,然后最后調(diào)用 close() 來關(guān)閉 socket 通道。
7.1.2 開始進(jìn)行 WebSocket 關(guān)閉握手用一個(gè)狀態(tài)碼 code (第 7.4 節(jié))和一個(gè)可選的關(guān)閉原因 reason (第 7.1.6 節(jié))來開始 WebSocket 關(guān)閉握手,終端必須發(fā)送一個(gè)在第 5.5.1 節(jié)中描述的一樣的關(guān)閉幀,將狀態(tài)碼設(shè)置為 code 字段,將關(guān)閉原因設(shè)置為 reaons 字段。一旦終端已經(jīng)發(fā)送和收到了關(guān)閉控制幀,那么終端應(yīng)該像第 7.1.1 節(jié)中定義的一樣關(guān)閉 WebSocket 連接。
7.1.3 已經(jīng)開始 WebSocket 關(guān)閉握手在發(fā)送或者收到了關(guān)閉幀時(shí),我們可以說已經(jīng)開始 WebSocket 關(guān)閉握手,并且 WebSocket 連接的狀態(tài)已經(jīng)到了“關(guān)閉中”(CLOSING)狀態(tài)。
7.1.4 WebSocket 連接已關(guān)閉當(dāng)?shù)讓拥?TCP 連接關(guān)閉后,我們可以說WebSocket 連接已關(guān)閉,并且 WebSocket 連接已經(jīng)到了”關(guān)閉“(CLOSED)狀態(tài)。如果 TCP 連接在 WebSocket 關(guān)閉握手完成之后已經(jīng)關(guān)閉,那么我們可以說 WebSocket 連接已經(jīng)被徹底關(guān)閉。
如果 WebSocket 連接沒有被建立,我們也說WebSocket已經(jīng)關(guān)閉,但是不徹底。
7.1.5 WebSocket 關(guān)閉狀態(tài)碼就像在第 5.5.1 和第 7.4 節(jié)中定義的一樣,關(guān)閉幀可以包含一個(gè)關(guān)閉的狀態(tài)碼和指定的原因。WebSocket 連接的關(guān)閉可能是同時(shí)由另一個(gè)終端發(fā)起。WebSocket 關(guān)閉狀態(tài)碼是在第 7.4 節(jié)中定義的在第一關(guān)閉幀中的由實(shí)現(xiàn)該協(xié)議的應(yīng)用程序接收的狀態(tài)碼。如果關(guān)閉幀中沒有包含狀態(tài)碼,WebSocket 關(guān)閉狀態(tài)碼被默認(rèn)為1005。如果WebSocket 已經(jīng)關(guān)閉并且終端沒有收到任何的關(guān)閉幀(例如發(fā)生了可能底層的傳輸連接突然丟失的情況),那么WebSocket 關(guān)閉狀態(tài)碼被默認(rèn)為1006。
注:兩個(gè)終端可能沒有就WebSocket 關(guān)閉狀態(tài)碼的值達(dá)成一致。例如:如果遠(yuǎn)端發(fā)送一個(gè)關(guān)閉幀,但是本地應(yīng)用沒有從它的 socket 緩沖區(qū)中讀到關(guān)閉幀的數(shù)據(jù),同時(shí)本地應(yīng)用多帶帶的決定關(guān)閉連接并且發(fā)送了一個(gè)關(guān)閉幀,那么兩個(gè)終端都發(fā)送了并且會(huì)收到一個(gè)關(guān)閉幀,同時(shí)不會(huì)發(fā)送更多的關(guān)閉幀。每一個(gè)終端會(huì)看到另一個(gè)終端發(fā)送過來的WebSocket 關(guān)閉狀態(tài)碼的狀態(tài)碼。像這樣的,在這個(gè)示例里面,有可能兩個(gè)終端都沒有協(xié)商過WebSocket 關(guān)閉狀態(tài)碼,兩個(gè)終端都幾乎在同一時(shí)間多帶帶開始 WebSocket 關(guān)閉握手。
7.1.6 WebSocket 連接關(guān)閉原因像第 5.5.1 節(jié)和第 7.4 節(jié)中定義的一樣,一個(gè)關(guān)閉幀可能包含一個(gè)用于關(guān)閉的表示原因的狀態(tài)碼,然后是 UTF-8 編碼的數(shù)據(jù),數(shù)據(jù)的解析方式是留給終端來解釋,而不在這個(gè)協(xié)議中定義。一個(gè)正在關(guān)閉中的 WebSocket 連接可能是同時(shí)從另一端開始的。WebSocket 連接關(guān)閉原因是實(shí)現(xiàn)了該協(xié)議的應(yīng)用收到的緊跟在狀態(tài)碼(第 7.4 節(jié))之后的包含在第一個(gè)關(guān)閉控制幀中的 UTF-8 編碼數(shù)據(jù)。如果在關(guān)閉控制幀中沒有這些數(shù)據(jù),那么WebSocket 連接關(guān)閉原因的值就是一個(gè)空字符串。
注:和在第 7.1.5 中被提到的邏輯一樣,兩個(gè)終端可能沒有協(xié)商過WebSocket 連接關(guān)閉原因。
7.1.7 WebSocket 連接失效某些算法和規(guī)范要求終端有WebSocket 連接失效。為了實(shí)現(xiàn)這些,客戶端必須關(guān)閉 WebSocket 連接,并且可以用一個(gè)合適的方式向用戶上報(bào)相關(guān)問題(尤其是對(duì)開發(fā)者有幫助的內(nèi)容)。相似的,為了實(shí)現(xiàn)這個(gè),服務(wù)端必須關(guān)閉 WebSocket 連接,并且應(yīng)該用日志記錄這個(gè)問題。
如果在此之前WebSocket 已經(jīng)建立連接,此時(shí)終端需要讓WebSocket 連接失效,那么在進(jìn)行關(guān)閉 WebSocket 連接之前,終端需要發(fā)送一個(gè)包含恰當(dāng)?shù)臓顟B(tài)碼(第 7.4 節(jié))。終端在確認(rèn)另一端沒有能力接收或者處理關(guān)閉幀時(shí),可能會(huì)選擇省略發(fā)送關(guān)閉幀,從而在一開始就進(jìn)入正常錯(cuò)誤流程導(dǎo)致 WebSocket 連接關(guān)閉。終端在接到WebSocket 連接失效的指令后,不能繼續(xù)嘗試處理來自另一端的數(shù)據(jù)(包括響應(yīng)的關(guān)閉幀)。
除了上面說到的場(chǎng)景和應(yīng)用層指定的場(chǎng)景(例如:腳本使用了 WebSocket 的 API)外,客戶端不應(yīng)該關(guān)閉連接。
7.2 異常關(guān)閉 7.2.1 客戶端主動(dòng)關(guān)閉在開始握手中的某些特定算法,需要客戶端讓WebSocket 連接失效。為了實(shí)現(xiàn)這些,客戶端必須像第 7.1.7 節(jié)中定義的一樣讓WebSocket 連接失敗。
如果任意一端底層的傳輸連接意外丟失,客戶端必須讓WebSocket 連接失敗。
除了上面指定的情況和應(yīng)用層的約束(例如,腳本使用了 WebSocket 的 API)外,客戶端不應(yīng)該關(guān)閉連接。
7.2.2 服務(wù)端主動(dòng)關(guān)閉在開始監(jiān)建立連接握手時(shí),有些算法要求或者推薦服務(wù)端終端 WebSocket 連接。為了實(shí)現(xiàn)這些,服務(wù)端必須關(guān)閉 WebSocket 連接(第 7.1.1 節(jié))。
7.2.3 從異常關(guān)閉中恢復(fù)導(dǎo)致異常關(guān)閉的原因有很多。例如是由于一個(gè)臨時(shí)的錯(cuò)誤導(dǎo)致的關(guān)閉,在這種情況下能夠恢復(fù)就能夠帶來一個(gè)穩(wěn)定的連接,恢復(fù)正常的操作。有些問題也有可能是一個(gè)非臨時(shí)的問題導(dǎo)致的,在這種情況下如果每個(gè)客戶端都遇到了異常的關(guān)閉,客戶端立刻重試連接并且不間斷情況下,服務(wù)端可能會(huì)收到由于大量客戶端重新連接帶來的拒絕服務(wù)攻擊。最終的結(jié)果就是這個(gè)方案可能會(huì)導(dǎo)致服務(wù)沒有辦法及時(shí)的恢復(fù),或者讓服務(wù)恢復(fù)變得困難的多。
為了避免這個(gè)問題,客戶端應(yīng)該在異常終端嘗試恢復(fù)連接時(shí),使用在這一節(jié)中定義的一些備選策略。
第一次嘗試恢復(fù)連接應(yīng)該在一個(gè)隨機(jī)長(zhǎng)度時(shí)間后。隨機(jī)事件的參數(shù)如何選擇,這個(gè)交給客戶端來決定;選擇 0 到 5 秒之間的隨機(jī)值是一個(gè)合理的初始延時(shí),但是客戶端可以根據(jù)自己的經(jīng)驗(yàn)和特定的應(yīng)用來選擇不同長(zhǎng)度的時(shí)間延時(shí)。
如果第一次重試連接失敗,接下來的連接的延時(shí)應(yīng)該變大,使用如截?cái)喽M(jìn)制指數(shù)退避方法(譯者注:解決以太網(wǎng)碰撞算法,見截?cái)喽M(jìn)制質(zhì)數(shù)退避算法)等來進(jìn)行設(shè)置這個(gè)延時(shí)。
7.3 連接正常關(guān)閉服務(wù)端可以在任意需要時(shí)關(guān)閉 WebSocket 連接。客戶端不應(yīng)該任意關(guān)閉 WebSocket 連接。在任一情況中,終端要發(fā)起關(guān)閉都必須遵循開始 WebSocket 連接關(guān)閉的步驟。
7.4 狀態(tài)碼當(dāng)關(guān)閉一個(gè)連接時(shí)(如:在開始握手已經(jīng)完成后,發(fā)送一個(gè)關(guān)閉幀),終端可能會(huì)說明關(guān)閉的原因。終端的這個(gè)原因的描述和終端應(yīng)該采取的行動(dòng),在這個(gè)文檔中都沒有說明。這個(gè)文檔提前定義了一些可能用于擴(kuò)展、框架和終端應(yīng)用的狀態(tài)碼和狀態(tài)碼范圍。這些狀態(tài)碼和任何有關(guān)聯(lián)的的文本消息在關(guān)閉幀中都是可選的。
7.4.1 定義狀態(tài)碼在發(fā)送一個(gè)關(guān)閉幀時(shí),終端可以提前定義如下的狀態(tài)碼。
1000
1000 表示一個(gè)正常的關(guān)閉,意味著連接建立的目標(biāo)已經(jīng)完成了。
1001
1001 表示終端已經(jīng)“走開”,例如服務(wù)器停機(jī)了或者在瀏覽器中離開了這個(gè)頁(yè)面。
1002
1002 表示終端由于協(xié)議錯(cuò)誤中止了連接。
1003
1003 表示終端由于收到了一個(gè)不支持的數(shù)據(jù)類型的數(shù)據(jù)(如終端只能怪理解文本數(shù)據(jù),但是收到了一個(gè)二進(jìn)制數(shù)據(jù))從而關(guān)閉連接。
1004
保留字段。這意味著這個(gè)狀態(tài)碼可能會(huì)在將來被定義。
1005
1005 是一個(gè)保留值并且不能被終端當(dāng)做一個(gè)關(guān)閉幀的狀態(tài)碼。這個(gè)狀態(tài)碼是為了給上層應(yīng)用表示當(dāng)前沒有狀態(tài)碼。
1006
1006 是一個(gè)保留值并且不能被終端當(dāng)做一個(gè)關(guān)閉幀的狀態(tài)碼。這個(gè)狀態(tài)碼是為了給上層應(yīng)用表示連接被異常關(guān)閉如沒有發(fā)送或者接受一個(gè)關(guān)閉幀這種場(chǎng)景的使用而設(shè)計(jì)的。
1007
1007 表示終端因?yàn)槭盏搅祟愋筒贿B續(xù)的消息(如非 UTF-8 編碼的文本消息)導(dǎo)致的連接關(guān)閉。
1008
1008 表示終端是因?yàn)槭盏搅艘粋€(gè)違反政策的消息導(dǎo)致的連接關(guān)閉。這是一個(gè)通用的狀態(tài)碼,可以在沒有什么合適的狀態(tài)碼(如 1003 或者 1009)時(shí)或者可能需要隱藏關(guān)于政策的具體信息時(shí)返回。
1009
1009 表示終端由于收到了一個(gè)太大的消息無法進(jìn)行處理從而關(guān)閉連接。
1010
1010 表示終端(客戶端)因?yàn)轭A(yù)期與服務(wù)端協(xié)商一個(gè)或者多個(gè)擴(kuò)展,但是服務(wù)端在 WebSocket 握手中沒有響應(yīng)這個(gè)導(dǎo)致的關(guān)閉。需要的擴(kuò)展清單應(yīng)該出現(xiàn)在關(guān)閉幀的原因(reason)字段中。
1001
1001 表示服務(wù)端因?yàn)橛龅搅艘粋€(gè)意外的條件阻止它完成這個(gè)請(qǐng)求從而導(dǎo)致連接關(guān)閉。
1015
1015 是一個(gè)保留值,不能被終端設(shè)置到關(guān)閉幀的狀態(tài)碼中。這個(gè)狀態(tài)碼是用于上層應(yīng)用來表示連接失敗是因?yàn)?TLS 握手失敗(如服務(wù)端證書沒有被驗(yàn)證過)導(dǎo)致的關(guān)閉的。
7.4.2 保留狀態(tài)碼范圍0-999
0-999 的狀態(tài)碼都沒有被使用。
1000-2999
1000-2999 的狀態(tài)碼是在這個(gè)文檔、將來的修訂和擴(kuò)展中定義的保留字段,用于永久的可用的公共文檔。
3000-3999
3000-3999 的狀態(tài)碼是保留給庫(kù)、框架和應(yīng)用使用的。這些狀態(tài)碼被IANA直接注冊(cè)了。這些狀態(tài)碼在這篇文檔中沒有進(jìn)行解釋。
4000-4999
40000-4999 的狀態(tài)碼是保留下來私用的,因此這些狀態(tài)碼不能被注冊(cè)。這些狀態(tài)碼可以使用在 WebSocket 應(yīng)用之前的協(xié)議上。這些狀態(tài)碼在這篇文檔中沒有進(jìn)行解釋。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/101850.html
摘要:概述經(jīng)過半年的搗鼓,終于將協(xié)議全篇翻譯完成。現(xiàn)在將所有章節(jié)全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的中查看。大家有相關(guān)類型的需要,建議大家可以嘗試下。 概述 經(jīng)過半年的搗鼓,終于將 WebSocket 協(xié)議(RFC6455)全篇翻譯完成。現(xiàn)在將所有章節(jié)全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的GitHub中查看。 具體章節(jié)...
摘要:最終形成服務(wù)器端的握手響應(yīng)必需。出于安全考慮和避免網(wǎng)絡(luò)截獲,客戶端發(fā)送的數(shù)據(jù)幀必須進(jìn)行掩碼處理后才能發(fā)送到服務(wù)器,不論是否是在安全協(xié)議上都要進(jìn)行掩碼處理。服務(wù)器如果沒有收到掩碼處理的數(shù)據(jù)幀時(shí)應(yīng)該關(guān)閉連接,發(fā)送一個(gè)的狀態(tài)碼。 首先 長(zhǎng)連接:一個(gè)連接上可以連續(xù)發(fā)送多個(gè)數(shù)據(jù)包,在連接期間,如果沒有數(shù)據(jù)包發(fā)送,需要雙方發(fā)鏈路檢查包。 TCP/IP:TCP/IP屬于傳輸層,主要解決數(shù)據(jù)在網(wǎng)絡(luò)中的...
摘要:服務(wù)端確認(rèn)協(xié)議版本,升級(jí)為協(xié)議。自己寫了一個(gè)例子,服務(wù)端在開始連接后,利用定時(shí)器主動(dòng)向客戶端發(fā)送隨機(jī)數(shù),客戶端也可以發(fā)給服務(wù)器消息,然后服務(wù)器返回這條消息給客戶端。 寫在前面 webSocket是一項(xiàng)可以讓服務(wù)器將數(shù)據(jù)主動(dòng)推送給客戶端的技術(shù)。前幾天寫了一個(gè)日志功能,日志數(shù)據(jù)需要實(shí)時(shí)更新。正好項(xiàng)目中有封裝好的WebSocket組件,且接口支持webSocket,就用它實(shí)現(xiàn)了。也是第一次用...
摘要:用實(shí)現(xiàn)簡(jiǎn)單協(xié)議從瀏覽器說起瀏覽器提供的非常簡(jiǎn)潔。創(chuàng)建連接連接建立時(shí)的回調(diào)收到消息時(shí)的回調(diào)連接出錯(cuò)時(shí)的回調(diào)連接終止時(shí)的回調(diào)發(fā)送消息告訴我們也就是說,在創(chuàng)建對(duì)象時(shí),瀏覽器嘗試與服務(wù)端建立連接發(fā)送請(qǐng)求建立個(gè)服務(wù)端一旦收到數(shù)據(jù),就會(huì)觸發(fā)。 用 Node 實(shí)現(xiàn)簡(jiǎn)單 WebSocket 協(xié)議 從瀏覽器 WebSocket API 說起 瀏覽器提供的 WebSocket API 非常簡(jiǎn)潔。 let...
摘要:服務(wù)端確認(rèn)協(xié)議版本,升級(jí)為協(xié)議。自己寫了一個(gè)例子,服務(wù)端在開始連接后,利用定時(shí)器主動(dòng)向客戶端發(fā)送隨機(jī)數(shù),客戶端也可以發(fā)給服務(wù)器消息,然后服務(wù)器返回這條消息給客戶端。做的事情就是給頁(yè)面的元素綁定事件。 寫在前面webSocket是一項(xiàng)可以讓服務(wù)器將數(shù)據(jù)主動(dòng)推送給客戶端的技術(shù)。前幾天寫了一個(gè)日志功能,日志數(shù)據(jù)需要實(shí)時(shí)更新。正好項(xiàng)目中有封裝好的WebSocket組件,且接口支持webSock...
閱讀 3403·2023-04-26 02:41
閱讀 2445·2023-04-26 00:14
閱讀 2823·2021-08-11 10:22
閱讀 1275·2019-12-27 11:38
閱讀 3571·2019-08-29 18:34
閱讀 2375·2019-08-29 12:13
閱讀 2951·2019-08-26 18:26
閱讀 1834·2019-08-26 16:49