RFC6455-The WebSocket protocol 之八:7. Closing the Connection & 8. Error Handling

7.  Closing the Connection

7.關閉連接

7.1.  Definitions

7.1 術語
7.1.1.  Close the WebSocket Connection

7.1.1 關閉WebSocket連接
   To _Close the WebSocket Connection_, an endpoint closes the
   underlying TCP connection.  An endpoint SHOULD use a method that
   cleanly closes the TCP connection, as well as the TLS session, if
   applicable, discarding any trailing bytes that may have been
   received.  An endpoint MAY close the connection via any means
   available when necessary, such as when under attack.
   The underlying TCP connection, in most normal cases, SHOULD be closed
   first by the server, so that it holds the TIME_WAIT state and not the
   client (as this would prevent it from re-opening the connection for 2
   maximum segment lifetimes (2MSL), while there is no corresponding
   server impact as a TIME_WAIT connection is immediately reopened upon
   a new SYN with a higher seq number).  In abnormal cases (such as not
   having received a TCP Close from the server after a reasonable amount
   of time) a client MAY initiate the TCP Close.  As such, when a server
   is instructed to _Close the WebSocket Connection_ it SHOULD initiate
   a TCP Close immediately, and when a client is instructed to do the
   same, it SHOULD wait for a TCP Close from the server.
   As an example of how to obtain a clean closure in C using Berkeley
   sockets, one would call shutdown() with SHUT_WR on the socket, call
   recv() until obtaining a return value of 0 indicating that the peer
   has also performed an orderly shutdown, and finally call close() on
   the socket.

要關閉WebSoket連接,終端需要關閉底層的TCP連接。終端需要使用一個方法乾淨的關閉TCP連接、TLS會話,如果可能的話,丟棄所有已收到數據之後的數據。必要的情況下,終端可以使用任何方式關閉連接,比如受到攻擊時。在大多數情況下,底層的TCP連接應該由服務端關閉,因爲服務端持有TIME_WAIT狀態而不是客戶端(客戶端將防止其在2段最大生命週期的間隔後才能打開連接,當沒有對應的服務端影響作爲等待時間時,連接會用一個更高的seq在一個新的SYN上立即打開)。反常情況下(例如在一個合理的時候後沒有從服務端接收到TCP關閉信號)客戶端可能會開啓TCP關閉。因此,當服務端打算要關閉WebSocket連接的時候,它需要立即啓動TCP關閉,當客戶打算這麼做的時候,它應該等服務端發送TCP關閉。舉個例子,在C中使用Berkeley sockets如何執行乾淨的關閉,需要在socket上調用shutdown(SHUT_WR)方法,然後調用recv方法直到獲得返回值0,這標誌着對方也已經按照順序進行了shutdown操作,最後調用close()。

7.1.2.  Start the WebSocket Closing Handshake
   To _Start the WebSocket Closing Handshake_ with a status code
   (Section 7.4) /code/ and an optional close reason (Section 7.1.6)
   /reason/, an endpoint MUST send a Close control frame, as described
   in Section 5.5.1, whose status code is set to /code/ and whose close
   reason is set to /reason/.  Once an endpoint has both sent and
   received a Close control frame, that endpoint SHOULD _Close the
   WebSocket Connection_ as defined in Section 7.1.1.

7.1.2 開始WebSocket關閉握手

開始一個WebSocket關閉握手需要包含一個狀態碼和一個可選的關閉原因,客戶端必須發送一個關閉控制數據包,其中code字段標識狀態碼,reason字段標識關閉原因。一旦終端發送並接收了關閉控制數據包,終端需要關閉WebSocket連接。


7.1.3.  The WebSocket Closing Handshake is Started
   Upon either sending or receiving a Close control frame, it is said
   that _The WebSocket Closing Handshake is Started_ and that the
   WebSocket connection is in the CLOSING state.

7.1.3 WebSocket關閉握手已經啓動

一旦接收或發送一個關閉控制數據包,標識着WebSocket關閉握手已經啓動,WebSocket連接處於CLOSING狀態。


7.1.4.  The WebSocket Connection is Closed
   When the underlying TCP connection is closed, it is said that _The
   WebSocket Connection is Closed_ and that the WebSocket connection is
   in the CLOSED state.  If the TCP connection was closed after the
   WebSocket closing handshake was completed, the WebSocket connection
   is said to have been closed _cleanly_.
   If the WebSocket connection could not be established, it is also said
   that _The WebSocket Connection is Closed_, but not _cleanly_.

7.1.4. WebSocket連接已經關閉

當底層的TCP連接關閉後就意味着WebSocket連接已經關閉,WebSocket連接處於CLOSED狀態。假如TCP連接在WebSocket關閉握手結束後關閉,則意味着WebSocket連接被幹淨的關閉了。


7.1.5.  The WebSocket Connection Close Code

7.1.5 WebSocket連接關閉碼
   As defined in Sections 5.5.1 and 7.4, a Close control frame may
   contain a status code indicating a reason for closure.  A closing of
   the WebSocket connection may be initiated by either endpoint,
   potentially simultaneously. _The WebSocket Connection Close Code_ is
   defined as the status code (Section 7.4) contained in the first Close
   control frame received by the application implementing this protocol.
   If this Close control frame contains no status code, _The WebSocket
   Connection Close Code_ is considered to be 1005.  If _The WebSocket
   Connection is Closed_ and no Close control frame was received by the
   endpoint (such as could occur if the underlying transport connection
   is lost), _The WebSocket Connection Close Code_ is considered to be
   1006.

如5.5.5和7.4中定義,一個關閉控制數據包會包含一個狀態碼來代表關閉的原因。WebSocket連接的關閉有可能被任何一個終端發起,有可能同時發起。實現了該協議的應用接收到的第一個關閉控制數據包中包含的狀態碼稱之爲:The WebSocket Connection Close Code。如果關閉控制數據包不包含狀態碼,The WebSocket Connection Close Code默認爲1005。假如連接被關閉但是終端沒有接收到關閉控制數據包(可能發生在底層連接丟失的情況下),The WebSocket Connection Close Code是1006。


   NOTE: Two endpoints may not agree on the value of _The WebSocket
   Connection Close Code_.  As an example, if the remote endpoint sent a
   Close frame but the local application has not yet read the data
   containing the Close frame from its socket’s receive buffer, and the
   local application independently decided to close the connection and
   send a Close frame, both endpoints will have sent and received a   Close frame and will not send further Close frames.  Each endpoint
   will see the status code sent by the other end as _The WebSocket
   Connection Close Code_.  As such, it is possible that the two
   endpoints may not agree on the value of _The WebSocket Connection
   Close Code_ in the case that both endpoints _Start the WebSocket
   Closing Handshake_ independently and at roughly the same time.

注意:兩個終端的WebSocket關閉碼的值可能不同。例如,一個遠程終端發送了關閉數據包,但是本地的應用還沒有讀取到這個關閉數據包的時候,它也決定關閉這個連接併發送了關閉數據包,兩個終端都發送並接收了關閉數據包,將來不會再發送關閉數據包。每個終端將把對方發送的錯誤碼作爲WebSocket Connection Close Code。


7.1.6.  The WebSocket Connection Close Reason

7.1.6 WebSocket連接關閉原因
   As defined in Sections 5.5.1 and 7.4, a Close control frame may
   contain a status code indicating a reason for closure, followed by
   UTF-8-encoded data, the interpretation of said data being left to the
   endpoints and not defined by this protocol.  A closing of the
   WebSocket connection may be initiated by either endpoint, potentially
   simultaneously. _The WebSocket Connection Close Reason_ is defined as
   the UTF-8-encoded data following the status code (Section 7.4)
   contained in the first Close control frame received by the
   application implementing this protocol.  If there is no such data in
   the Close control frame, _The WebSocket Connection Close Reason_ is
   the empty string.
   NOTE: Following the same logic as noted in Section 7.1.5, two
   endpoints may not agree on _The WebSocket Connection Close Reason_.

像5.5.1和7.4所說的,一個關閉控制數據包可以包含一個狀態碼標記關閉的原因,在它後面是UTF-8編碼的數據,這些數據的解析留給了終端,並沒有在協議中定義。WebSocket連接的關閉可以由任何一個終端同時發起。在狀態碼後面的UTF-8編碼的數據是關閉的原因,它在協議的應用接收的第一個關閉控制數據包中。假如關閉控制數據包中沒有這樣的數據,WebSocket連接關閉的原因是空字符串。

注意:遵從7.1.5中的提到的邏輯,兩個終端在WebSocket連接關閉原因上可能不一致。


7.1.7.  Fail the WebSocket Connection
   Certain algorithms and specifications require an endpoint to _Fail
   the WebSocket Connection_.  To do so, the client MUST _Close the
   WebSocket Connection_, and MAY report the problem to the user (which
   would be especially useful for developers) in an appropriate manner.
   Similarly, to do so, the server MUST _Close the WebSocket
   Connection_, and SHOULD log the problem.
   If _The WebSocket Connection is Established_ prior to the point where
   the endpoint is required to _Fail the WebSocket Connection_, the
   endpoint SHOULD send a Close frame with an appropriate status code
   (Section 7.4) before proceeding to _Close the WebSocket Connection_.
   An endpoint MAY omit sending a Close frame if it believes the other
   side is unlikely to be able to receive and process the Close frame,
   due to the nature of the error that led the WebSocket connection to
   fail in the first place.  An endpoint MUST NOT continue to attempt to
   process data (including a responding Close frame) from the remote
   endpoint after being instructed to _Fail the WebSocket Connection_.
   Except as indicated above or as specified by the application layer
   (e.g., a script using the WebSocket API), clients SHOULD NOT close
   the connection.

7.1.7 釋放WebSocket連接

某些算法和說明書要求終端去釋放WebSocket連接。爲了這個目的,客戶端必須關閉WebSocket連接,並以適當的方式把問題(尤其對開發者非常有用)上報給用戶。最簡單的方式就是服務端在關閉WebSocket連接的時候,記錄問題日誌。

假如WebSocket連接建立的時候要求終端釋放連接,終端在釋放連接之前需要設置一個包含錯誤碼的關閉數據包。假如終端認爲對方無法接收並處理關閉數據包,它可能不會發送關閉數據包,由於該錯誤的自然性(nature)致使它成爲WebSocket連接失敗的罪魁禍首。一個終端在得到釋放WebSocket連接的指示後,不應該再持續從遠程終端獲取的數據。除去上述定義或應用層特殊定義,客戶端不應該關閉連接。


7.2.  Abnormal Closures

7.2 異常關閉
7.2.1.  Client-Initiated Closure

7.2.1客戶端發起關閉
   Certain algorithms, in particular during the opening handshake,
   require the client to _Fail the WebSocket Connection_.  To do so, the
   client MUST _Fail the WebSocket Connection_ as defined in
   Section 7.1.7.
   If at any point the underlying transport layer connection is
   unexpectedly lost, the client MUST _Fail the WebSocket Connection_.
   Except as indicated above or as specified by the application layer
   (e.g., a script using the WebSocket API), clients SHOULD NOT close
   the connection.

某些算法,由其是在打開握手時,要求客戶端去釋放WebSocket連接。爲此,客戶端必須像7.1.7中定義的釋放WebSocket連接。

在任何情況下底層的傳輸層意外丟失,客戶端必須釋放WebSocket連接。除去上述定義或應用層特殊定義,客戶端不應該關閉連接。
7.2.2.  Server-Initiated Closure
   Certain algorithms require or recommend that the server _Abort the
   WebSocket Connection_ during the opening handshake.  To do so, the
   server MUST simply _Close the WebSocket Connection_ (Section 7.1.1).

7.2.2 服務端發起關閉

某些算法要求或建議服務端在打開握手時終止WebSocket連接。爲此服務端必須簡單的關閉WebSocket連接。


7.2.3.  Recovering from Abnormal Closure

7.2.3 從異常關閉恢復
   Abnormal closures may be caused by any number of reasons.  Such
   closures could be the result of a transient error, in which case
   reconnecting may lead to a good connection and a resumption of normal
   operations.  Such closures may also be the result of a nontransient
   problem, in which case if each deployed client experiences an
   abnormal closure and immediately and persistently tries to reconnect,
   the server may experience what amounts to a denial-of-service attack
   by a large number of clients trying to reconnect.  The end result of
   such a scenario could be that the service is unable to recover in a
   timely manner or recovery is made much more difficult.

異常關閉可能由很多原因引起。在僅僅是臨時錯誤引起的關閉情況下,恢復連接可以獲得一個好的連接並使操作恢復正常。這種關閉也可能是非臨時錯誤引起的,這種情況下假如每一個部署的客戶端都經歷了異常關閉然後立即重新連接,服務端將會由於大量的客戶端準備去重新連接而遭受到服務器拒絕服務攻擊。這種情景的最終結果是服務端不能及時恢復或者致使恢復過程非常複雜。
   To prevent this, clients SHOULD use some form of backoff when trying
   to reconnect after abnormal closures as described in this section.
   The first reconnect attempt SHOULD be delayed by a random amount of
   time.  The parameters by which this random delay is chosen are left
   to the client to decide; a value chosen randomly between 0 and 5
   seconds is a reasonable initial delay though clients MAY choose a
   different interval from which to select a delay length based on
   implementation experience and particular application.
   Should the first reconnect attempt fail, subsequent reconnect
   attempts SHOULD be delayed by increasingly longer amounts of time,
   using a method such as truncated binary exponential backoff.

爲了避免這種情況,客戶端在遇到本節說的異常關閉後重新連接時需要某種形式的補償。第一個重連請求需要有一個隨機時間的等待。客戶端決定影響隨機等待時間的參數;在0到5秒之間隨機選擇的數字是一個合理的初始值,因此客戶端從哪裏選一個不同的時間間隔取決於實施經驗和特定應用。當第一次重連失敗,後續的重連需要等待更長的時間,可以使用類似於二進制指數(truncated binary exponential backoff)的方法。

7.3.  Normal Closure of Connections

7.3正常關閉連接
   Servers MAY close the WebSocket connection whenever desired.  Clients
   SHOULD NOT close the WebSocket connection arbitrarily.  In either
   case, an endpoint initiates a closure by following the procedures to
   _Start the WebSocket Closing Handshake_ (Section 7.1.2).

服務端可以在任何期望的時候關閉WebSocket連接。客戶端不能強制關閉WebSocket連接。在兩種情況下,一個終端按照7.1.2中的步驟啓動WebSocket關閉握手而啓動關閉。

7.4.  Status Codes

7.4 狀態碼
   When closing an established connection (e.g., when sending a Close
   frame, after the opening handshake has completed), an endpoint MAY
   indicate a reason for closure.  The interpretation of this reason by
   an endpoint, and the action an endpoint should take given this
   reason, are left undefined by this specification.  This specification
   defines a set of pre-defined status codes and specifies which ranges
   may be used by extensions, frameworks, and end applications.  The
   status code and any associated textual message are optional
   components of a Close frame.

當關閉一個連接時(當打開握手已經關閉後發送一個關閉數據包),終端可能提示關閉原因。終端如何解析原因、終端如何給出原因都沒有在說明書中定義。該說明書定義了一些狀態碼並指定了擴展、框架、高端應用的狀態碼範圍。在關閉數據包中狀態碼以及相關的文本信息都是可選的。
7.4.1.  Defined Status Codes

7.4.1 已定義的狀態碼
   Endpoints MAY use the following pre-defined status codes when sending
   a Close frame.

當終端發送一個關閉數據包時可能會用到後面定義的狀態碼。
   1000
      1000 indicates a normal closure, meaning that the purpose for
      which the connection was established has been fulfilled.

1000 代表正常關閉,意思是建立的連接已經完成。
   1001
      1001 indicates that an endpoint is "going away", such as a server
      going down or a browser having navigated away from a page.

1001代表終端要離開,如服務端關機或者瀏覽器從一個頁面離開。
   1002
      1002 indicates that an endpoint is terminating the connection due
      to a protocol error.

1002代表終端由於協議錯誤終止連接。
   1003
      1003 indicates that an endpoint is terminating the connection
      because it has received a type of data it cannot accept (e.g., an
      endpoint that understands only text data MAY send this if it
      receives a binary message).

1003代表終端由於無法承擔接收的數據而終止連接(例如一個僅接收文本的終端如果接收到了二進制信息會發送這個狀態碼)。

   1004
      Reserved.  The specific meaning might be defined in the future.

1004保留,可能會在將來定義。
   1005
      1005 is a reserved value and MUST NOT be set as a status code in a
      Close control frame by an endpoint.  It is designated for use in
      applications expecting a status code to indicate that no status
      code was actually present.

1005被保留,不能在終端發送的關閉控制數據包中作爲狀態碼存在。它被設計用在應用中,表示沒有狀態碼實際存在。
   1006
      1006 is a reserved value and MUST NOT be set as a status code in a
      Close control frame by an endpoint.  It is designated for use in
      applications expecting a status code to indicate that the
      connection was closed abnormally, e.g., without sending or
      receiving a Close control frame.

1006被保留,不能在終端發送的關閉控制數據包中作爲狀態碼存在。它被設計用在應用中,表示連接異常關閉的狀態碼,例如沒有發送或接收一個關閉控制數據包。
   1007
      1007 indicates that an endpoint is terminating the connection
      because it has received data within a message that was not
      consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
      data within a text message).

1007代表一個終端由於接收到的消息中的數據與消息類型不匹配而去關閉連接。


   1008
      1008 indicates that an endpoint is terminating the connection
      because it has received a message that violates its policy.  This
      is a generic status code that can be returned when there is no
      other more suitable status code (e.g., 1003 or 1009) or if there
      is a need to hide specific details about the policy.

1008代表一個終端由於接收到的消息違反了協議而去停止連接。這個是一般性狀態標誌,當沒有合適的狀態碼或需要隱藏具體細節的時候可以返回這個狀態碼。
   1009
      1009 indicates that an endpoint is terminating the connection
      because it has received a message that is too big for it to
      process.

1009代表一個終端由於接收到了太大的不能處理的數據,而去停止連接。
   1010
      1010 indicates that an endpoint (client) is terminating the
      connection because it has expected the server to negotiate one or
      more extension, but the server didn’t return them in the response
      message of the WebSocket handshake.  The list of extensions that      are needed SHOULD appear in the /reason/ part of the Close frame.

      Note that this status code is not used by the server, because it
      can fail the WebSocket handshake instead.

1010代表客戶端正在停止連接,因爲客戶端期望服務端支撐一個或多個擴展,但是服務端在WebSocket握手的響應消息中沒有包含它們。擴展的列表應該在關閉數據包的reason字段出現。注意這個狀態碼不能被服務端使用,因爲它反而會釋放WebSocket握手。
   1011
      1011 indicates that a server is terminating the connection because
      it encountered an unexpected condition that prevented it from
      fulfilling the request.

1011代表服務端正在停止連接,原因是它遇到了意料之外的情況不能完成請求。
   1015
      1015 is a reserved value and MUST NOT be set as a status code in a
      Close control frame by an endpoint.  It is designated for use in
      applications expecting a status code to indicate that the
      connection was closed due to a failure to perform a TLS handshake
      (e.g., the server certificate can’t be verified).

1015被保留,不能在終端發送的關閉控制數據包中作爲狀態碼存在。它被設計用在應用中,代表連接是在進行TLS握手時失敗而造成的關閉。
7.4.2.  Reserved Status Code Ranges

7.4.2 保留狀態碼的範圍
   0-999
      Status codes in the range 0-999 are not used.

0-999

0-999的狀態碼沒有使用。
   1000-2999
      Status codes in the range 1000-2999 are reserved for definition by
      this protocol, its future revisions, and extensions specified in a
      permanent and readily available public specification.

1000-2999

1000-2999的狀態碼預留給協議定義使用,未來的修訂、長久的擴展、現成的規範。

   3000-3999
      Status codes in the range 3000-3999 are reserved for use by
      libraries, frameworks, and applications.  These status codes are
      registered directly with IANA.  The interpretation of these codes
      is undefined by this protocol.

3000-3999

3000-3999的狀態碼預留給函數庫、框架和應用程序。這些代碼被IANA直接註冊。這些編碼的解析不在這個協議中定義。
   4000-4999
      Status codes in the range 4000-4999 are reserved for private use
      and thus can’t be registered.  Such codes can be used by prior
      agreements between WebSocket applications.  The interpretation of
      these codes is undefined by this protocol.

4000-4999的狀態碼是爲了私用而預留的,不能重新註冊。這種編碼可以優先用在多個WebSocket應用中。這些編碼的解析不在這個協議中定義。

8.  Error Handling
8.1.  Handling Errors in UTF-8-Encoded Data
   When an endpoint is to interpret a byte stream as UTF-8 but finds
   that the byte stream is not, in fact, a valid UTF-8 stream, that
   endpoint MUST _Fail the WebSocket Connection_.  This rule applies
   both during the opening handshake and during subsequent data
   exchange.

8.錯誤處理

8.1 使用UTF-8編碼數據處理錯誤

假如終端打算解析一個UTF-8編碼的二進制流,但是發現字節流不是合法的UTF-8流,終端會立即釋放WebSocket連接。這個規則同時適用於打開握手以及數據交互的過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章