```text
Internet Engineering Task Force (IETF) I. Fette
Request for Comments: 6455 Google, Inc.
Category: Standards Track A. Melnikov
ISSN: 2070-1721 Isode Ltd.
December 2011
The WebSocket Protocol
```
---
# **Abstract**
WebSocket 프로토콜은 제어된 환경에서 신뢰할 수 없는 코드를 실행하는 클라이언트와 해당 코드로부터의 통신을 선택한 원격 호스트 간의 양방향 통신을 가능하게 합니다. 이에 사용되는 보안 모델은 웹 브라우저에서 일반적으로 사용하는 원본 기반 보안 모델입니다. 프로토콜은 TCP를 통해 계층화된 기본 메시지 프레이밍과 뒤따르는 오프닝 핸드셰이크로 구성됩니다. 이 기술의 목표는 여러 HTTP 연결 열기\(예: XMLHttpRequest 또는 <iframe\> 및 긴 폴링 사용\)에 의존하지 않는 서버와의 양방향 통신이 필요한 브라우저 기반 애플리케이션을 위한 메커니즘을 제공하는 것입니다.
---
# **Status of This Memo**
이것은 인터넷 표준 추적 문서입니다.
이 문서는 IETF\(Internet Engineering Task Force\)의 제품입니다. 이는 IETF 커뮤니티의 합의를 나타냅니다. 공개 검토를 받았으며 IESG\(Internet Engineering Steering Group\)의 출판 승인을 받았습니다. 인터넷 표준에 대한 자세한 내용은 RFC 5741의 섹션 2에서 확인할 수 있습니다.
이 문서의 현재 상태, 정오표, 피드백 제공 방법에 대한 정보는 http://www.rfc-editor.org/info/rfc6455에서 얻을 수 있습니다.
---
# **Copyright Notice**
Copyright \(c\) 2011 IETF Trust 및 문서 작성자로 확인된 사람. 판권 소유.
이 문서는 이 문서 발행일에 유효한 BCP 78 및 IETF 문서와 관련된 IETF Trust의 법적 조항\(http://trustee.ietf.org/license-info\)의 적용을 받습니다. 이 문서에 관한 귀하의 권리와 제한 사항이 설명되어 있으므로 이 문서를 주의 깊게 검토하십시오. 이 문서에서 추출된 코드 구성 요소는 다음을 충족해야 합니다.
Trust Legal 조항의 섹션 4.e에 설명된 대로 단순화된 BSD 라이센스 텍스트를 포함하며 단순화된 BSD 라이센스에 설명된 대로 보증 없이 제공됩니다.
---
# **Table of Contents**
```text
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1. Background . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2. Protocol Overview . . . . . . . . . . . . . . . . . . . . 5
1.3. Opening Handshake . . . . . . . . . . . . . . . . . . . . 6
1.4. Closing Handshake . . . . . . . . . . . . . . . . . . . . 9
1.5. Design Philosophy . . . . . . . . . . . . . . . . . . . . 9
1.6. Security Model . . . . . . . . . . . . . . . . . . . . . . 10
1.7. Relationship to TCP and HTTP . . . . . . . . . . . . . . . 11
1.8. Establishing a Connection . . . . . . . . . . . . . . . . 11
1.9. Subprotocols Using the WebSocket Protocol . . . . . . . . 12
2. Conformance Requirements . . . . . . . . . . . . . . . . . . . 12
2.1. Terminology and Other Conventions . . . . . . . . . . . . 13
3. WebSocket URIs . . . . . . . . . . . . . . . . . . . . . . . . 14
4. Opening Handshake . . . . . . . . . . . . . . . . . . . . . . 14
4.1. Client Requirements . . . . . . . . . . . . . . . . . . . 14
4.2. Server-Side Requirements . . . . . . . . . . . . . . . . . 20
4.2.1. Reading the Client's Opening Handshake . . . . . . . . 21
4.2.2. Sending the Server's Opening Handshake . . . . . . . . 22
4.3. Collected ABNF for New Header Fields Used in Handshake . . 25
4.4. Supporting Multiple Versions of WebSocket Protocol . . . . 26
5. Data Framing . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.2. Base Framing Protocol . . . . . . . . . . . . . . . . . . 28
5.3. Client-to-Server Masking . . . . . . . . . . . . . . . . . 32
5.4. Fragmentation . . . . . . . . . . . . . . . . . . . . . . 33
5.5. Control Frames . . . . . . . . . . . . . . . . . . . . . . 36
5.5.1. Close . . . . . . . . . . . . . . . . . . . . . . . . 36
5.5.2. Ping . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.5.3. Pong . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.6. Data Frames . . . . . . . . . . . . . . . . . . . . . . . 38
5.7. Examples . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.8. Extensibility . . . . . . . . . . . . . . . . . . . . . . 39
6. Sending and Receiving Data . . . . . . . . . . . . . . . . . . 39
6.1. Sending Data . . . . . . . . . . . . . . . . . . . . . . . 39
6.2. Receiving Data . . . . . . . . . . . . . . . . . . . . . . 40
7. Closing the Connection . . . . . . . . . . . . . . . . . . . . 41
7.1. Definitions . . . . . . . . . . . . . . . . . . . . . . . 41
7.1.1. Close the WebSocket Connection . . . . . . . . . . . . 41
7.1.2. Start the WebSocket Closing Handshake . . . . . . . . 42
7.1.3. The WebSocket Closing Handshake is Started . . . . . . 42
7.1.4. The WebSocket Connection is Closed . . . . . . . . . . 42
7.1.5. The WebSocket Connection Close Code . . . . . . . . . 42
7.1.6. The WebSocket Connection Close Reason . . . . . . . . 43
7.1.7. Fail the WebSocket Connection . . . . . . . . . . . . 43
7.2. Abnormal Closures . . . . . . . . . . . . . . . . . . . . 44
7.2.1. Client-Initiated Closure . . . . . . . . . . . . . . . 44
7.2.2. Server-Initiated Closure . . . . . . . . . . . . . . . 44
7.2.3. Recovering from Abnormal Closure . . . . . . . . . . . 44
7.3. Normal Closure of Connections . . . . . . . . . . . . . . 45
7.4. Status Codes . . . . . . . . . . . . . . . . . . . . . . . 45
7.4.1. Defined Status Codes . . . . . . . . . . . . . . . . . 45
7.4.2. Reserved Status Code Ranges . . . . . . . . . . . . . 47
8. Error Handling . . . . . . . . . . . . . . . . . . . . . . . . 48
8.1. Handling Errors in UTF-8-Encoded Data . . . . . . . . . . 48
9. Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.1. Negotiating Extensions . . . . . . . . . . . . . . . . . . 48
9.2. Known Extensions . . . . . . . . . . . . . . . . . . . . . 50
10. Security Considerations . . . . . . . . . . . . . . . . . . . 50
10.1. Non-Browser Clients . . . . . . . . . . . . . . . . . . . 50
10.2. Origin Considerations . . . . . . . . . . . . . . . . . . 50
10.3. Attacks On Infrastructure (Masking) . . . . . . . . . . . 51
10.4. Implementation-Specific Limits . . . . . . . . . . . . . . 52
10.5. WebSocket Client Authentication . . . . . . . . . . . . . 53
10.6. Connection Confidentiality and Integrity . . . . . . . . . 53
10.7. Handling of Invalid Data . . . . . . . . . . . . . . . . . 53
10.8. Use of SHA-1 by the WebSocket Handshake . . . . . . . . . 54
11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 54
11.1. Registration of New URI Schemes . . . . . . . . . . . . . 54
11.1.1. Registration of "ws" Scheme . . . . . . . . . . . . . 54
11.1.2. Registration of "wss" Scheme . . . . . . . . . . . . . 55
11.2. Registration of the "WebSocket" HTTP Upgrade Keyword . . . 56
11.3. Registration of New HTTP Header Fields . . . . . . . . . . 57
11.3.1. Sec-WebSocket-Key . . . . . . . . . . . . . . . . . . 57
11.3.2. Sec-WebSocket-Extensions . . . . . . . . . . . . . . . 58
11.3.3. Sec-WebSocket-Accept . . . . . . . . . . . . . . . . . 58
11.3.4. Sec-WebSocket-Protocol . . . . . . . . . . . . . . . . 59
11.3.5. Sec-WebSocket-Version . . . . . . . . . . . . . . . . 60
11.4. WebSocket Extension Name Registry . . . . . . . . . . . . 61
11.5. WebSocket Subprotocol Name Registry . . . . . . . . . . . 61
11.6. WebSocket Version Number Registry . . . . . . . . . . . . 62
11.7. WebSocket Close Code Number Registry . . . . . . . . . . . 64
11.8. WebSocket Opcode Registry . . . . . . . . . . . . . . . . 65
11.9. WebSocket Framing Header Bits Registry . . . . . . . . . . 66
12. Using the WebSocket Protocol from Other Specifications . . . . 66
13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 67
14. References . . . . . . . . . . . . . . . . . . . . . . . . . . 68
14.1. Normative References . . . . . . . . . . . . . . . . . . . 68
14.2. Informative References . . . . . . . . . . . . . . . . . . 69
```
---
## **1. Introduction**
---
### **1.1. Background**
\_이 섹션은 비표준 섹션입니다.\_
역사적으로 클라이언트와 서버 간의 양방향 통신이 필요한 웹 애플리케이션\(예: 인스턴트 메시징 및 게임 애플리케이션\)을 만들려면 업스트림 알림을 별개의 HTTP 호출\[RFC6202\]로 보내는 동시에 업데이트를 위해 서버를 폴링하기 위해 HTTP를 남용해야 했습니다.
이로 인해 다양한 문제가 발생합니다.
o 서버는 각 클라이언트에 대해 다양한 기본 TCP 연결을 사용해야 합니다. 하나는 클라이언트에 정보를 전송하기 위한 것이고 다른 하나는 들어오는 메시지마다 새로운 것입니다.
o 유선 프로토콜은 각 클라이언트-서버 메시지에 HTTP 헤더가 있으므로 오버헤드가 높습니다.
o 클라이언트 측 스크립트는 응답을 추적하기 위해 나가는 연결에서 들어오는 연결로의 매핑을 유지해야 합니다.
더 간단한 해결책은 양방향 트래픽에 단일 TCP 연결을 사용하는 것입니다. 이것이 WebSocket 프로토콜이 제공하는 것입니다. WebSocket API\[WSAPI\]와 결합되어 웹 페이지에서 원격 서버로의 양방향 통신을 위한 HTTP 폴링에 대한 대안을 제공합니다.
게임, 주식 시세 표시기, 동시 편집이 가능한 다중 사용자 애플리케이션, 서버측 서비스를 실시간으로 노출하는 사용자 인터페이스 등 다양한 웹 애플리케이션에 동일한 기술을 사용할 수 있습니다.
WebSocket 프로토콜은 기존 인프라\(프록시, 필터링, 인증\)의 이점을 활용하기 위해 HTTP를 전송 계층으로 사용하는 기존 양방향 통신 기술을 대체하도록 설계되었습니다. HTTP는 처음에는 양방향 통신에 사용되도록 의도되지 않았기 때문에 이러한 기술은 효율성과 안정성 사이의 절충안으로 구현되었습니다\(자세한 논의는 \[RFC6202\] 참조\). WebSocket 프로토콜은 기존 HTTP 인프라의 맥락에서 기존 양방향 HTTP 기술의 목표를 해결하려고 시도합니다. 따라서 이는 HTTP 포트 80 및 443을 통해 작동하고 HTTP 프록시 및 중개자를 지원하도록 설계되었습니다. 비록 이것이 현재 환경에 특정한 복잡성을 암시하더라도 말입니다. 그러나 디자인은 WebSocket을 HTTP로 제한하지 않으며 향후 구현에서는 더 간단한 핸드셰이크를 사용할 수 있습니다.
전체 프로토콜을 재창조하지 않고도 전용 포트를 사용할 수 있습니다. 대화형 메시징의 트래픽 패턴은 표준 HTTP 트래픽과 거의 일치하지 않고 일부 구성 요소에 비정상적인 로드를 유발할 수 있으므로 이 마지막 사항이 중요합니다.
---
### **1.2. Protocol Overview**
\_이 섹션은 비표준 섹션입니다.\_
프로토콜은 핸드셰이크와 데이터 전송이라는 두 부분으로 구성됩니다.
클라이언트의 핸드셰이크는 다음과 같습니다.
```text
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
```
서버의 핸드셰이크는 다음과 같습니다.
```text
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
```
클라이언트의 선행 라인은 요청 라인 형식을 따릅니다. 서버의 선행 줄은 상태 줄 형식을 따릅니다. Request-Line 및 Status-Line 생성은 \[RFC2616\]에 정의되어 있습니다.
두 경우 모두 순서가 지정되지 않은 헤더 필드 세트가 선행 줄 뒤에 옵니다. 이러한 헤더 필드의 의미는 이 문서의 섹션 4에 명시되어 있습니다. 쿠키\[RFC6265\]와 같은 추가 헤더 필드가 있을 수도 있습니다. 헤더의 형식과 구문 분석은 \[RFC2616\]에 정의되어 있습니다.
클라이언트와 서버가 모두 핸드셰이크를 보내고 핸드셰이크가 성공하면 데이터 전송 부분이 시작됩니다. 이는 양측이 서로 독립적으로 원하는 대로 데이터를 보낼 수 있는 양방향 통신 채널입니다.
성공적인 핸드셰이크 후 클라이언트와 서버는 이 사양에서 "메시지"라고 하는 개념 단위로 데이터를 앞뒤로 전송합니다. 유선상에서 메시지는 하나 이상의 메시지로 구성됩니다.
프레임. WebSocket 메시지는 조각화된 메시지가 중개자에 의해 합쳐지거나 분할될 수 있으므로 특정 네트워크 계층 프레이밍에 반드시 대응할 필요는 없습니다.
프레임에는 연관된 유형이 있습니다. 동일한 메시지에 속하는 각 프레임에는 동일한 유형의 데이터가 포함됩니다. 광범위하게 말하면 텍스트 데이터\(UTF-8 \[RFC3629\] 텍스트로 해석됨\), 바이너리 데이터\(해석은 애플리케이션에 달려 있음\) 및 제어 프레임\(애플리케이션에 대한 데이터를 전달하기 위한 것이 아님\)에 대한 유형이 있습니다. 대신 연결을 닫아야 한다는 신호와 같은 프로토콜 수준 신호에 사용됩니다. 이 버전의 프로토콜은 6개의 프레임 유형을 정의하고 10개는 향후 사용을 위해 예약해 둡니다.
---
### **1.3. Opening Handshake**
\_이 섹션은 비표준 섹션입니다.\_
오프닝 핸드셰이크는 HTTP 기반 서버 측 소프트웨어 및 중개자와 호환되도록 설계되었으므로 해당 서버와 통신하는 HTTP 클라이언트와 해당 서버와 통신하는 WebSocket 클라이언트 모두에서 단일 포트를 사용할 수 있습니다. 이를 위해 WebSocket 클라이언트의 핸드셰이크는 HTTP 업그레이드 요청입니다.
```text
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
```
\[RFC2616\]에 따라 핸드셰이크의 헤더 필드는 클라이언트에 의해 임의의 순서로 전송될 수 있으므로 다른 헤더 필드가 수신되는 순서는 중요하지 않습니다.
GET 메서드 \[RFC2616\]의 "요청-URI"는 WebSocket 연결의 끝점을 식별하는 데 사용되며, 둘 다 하나의 IP 주소에서 여러 도메인이 제공되도록 허용하고 단일 서버에서 여러 WebSocket 끝점이 제공되도록 허용합니다.
클라이언트는 |호스트| \[RFC2616\]에 따라 핸드셰이크의 헤더 필드를 사용하여 클라이언트와 서버 모두 사용 중인 호스트에 동의하는지 확인할 수 있습니다.
추가 헤더 필드는 WebSocket 프로토콜에서 옵션을 선택하는 데 사용됩니다. 이 버전에서 사용할 수 있는 일반적인 옵션은 하위 프로토콜 선택기\(|Sec-WebSocket-Protocol|\), 클라이언트가 지원하는 확장 목록\(|Sec-WebSocket-Extensions|\), |Origin| 헤더 필드 등. |Sec-WebSocket-Protocol| 요청 헤더 필드는 클라이언트가 허용할 수 있는 하위 프로토콜\(WebSocket 프로토콜 위에 계층화된 애플리케이션 수준 프로토콜\)을 나타내는 데 사용될 수 있습니다. 서버는 허용되는 프로토콜 중 하나를 선택하거나 전혀 선택하지 않고 해당 프로토콜을 선택했음을 나타내기 위해 핸드셰이크에 해당 값을 표시합니다.
```text
Sec-WebSocket-Protocol: chat
```
|원산지| 헤더 필드 \[RFC6454\]는 웹 브라우저에서 WebSocket API를 사용하는 스크립트에 의한 WebSocket 서버의 승인되지 않은 교차 원본 사용을 방지하는 데 사용됩니다. 서버는 WebSocket 연결 요청을 생성하는 스크립트 원본에 대한 정보를 받습니다. 서버가 이 원본으로부터의 연결을 수락하지 않으려면 적절한 HTTP 오류 코드를 전송하여 연결을 거부하도록 선택할 수 있습니다. 이 헤더 필드는 브라우저 클라이언트에서 전송됩니다. 브라우저가 아닌 클라이언트의 경우 해당 클라이언트의 컨텍스트에 적합하다면 이 헤더 필드가 전송될 수 있습니다.
마지막으로, 서버는 클라이언트의 WebSocket 핸드셰이크를 수신했음을 클라이언트에 증명해야 서버가 WebSocket 연결이 아닌 연결을 허용하지 않습니다. 이는 공격자가 XMLHttpRequest \[XMLHttpRequest\] 또는 양식 제출을 사용하여 신중하게 제작된 패킷을 보내 WebSocket 서버를 속이는 것을 방지합니다.
핸드셰이크가 수신되었음을 증명하기 위해 서버는 두 가지 정보를 가져와 결합하여 응답을 생성해야 합니다. 첫 번째 정보는 |Sec-WebSocket-Key| 클라이언트 핸드셰이크의 헤더 필드:
```text
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
```
이 헤더 필드의 경우 서버는 헤더 필드에 있는 값\(예: base64로 인코딩된 \[RFC4648\] 버전에서 선행 및 후행 공백을 뺀 값\)을 가져와 이를 전역 고유 식별자\(GUID, \[RFC4122\)와 연결해야 합니다. \]\) "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 문자열 형식으로, WebSocket 프로토콜을 이해하지 못하는 네트워크 엔드포인트에서는 사용되지 않을 것입니다. 그러면 이 연결의 SHA-1 해시\(160비트\) \[FIPS.180-3\], base64로 인코딩된\(\[RFC4648\] 섹션 4 참조\)이 서버의 핸드셰이크에 반환됩니다.
구체적으로 위의 예와 같이 |Sec-WebSocket-Key| 헤더 필드의 값이 "dGhlIHNhbXBsZSBub25jZQ=="인 경우 서버는 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 문자열을 연결하여 "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B" 문자열을 구성합니다. 11". 그런 다음 서버는 이에 대한 SHA-1 해시를 가져와 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea 값을 제공합니다. 그런 다음 이 값은 "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=" 값을 제공하기 위해 base64로 인코딩됩니다\(\[RFC4648\]의 섹션 4 참조\). 그러면 이 값은 |Sec-WebSocket-Accept| 헤더 필드.
서버에서의 핸드셰이크는 클라이언트 핸드셰이크보다 훨씬 간단합니다. 첫 번째 줄은 상태 코드 101을 포함하는 HTTP 상태 줄입니다.
```text
HTTP/1.1 101 Switching Protocols
```
101 이외의 상태 코드는 WebSocket 핸드셰이크가 완료되지 않았으며 HTTP 의미가 여전히 적용됨을 나타냅니다. 헤더는 상태 코드를 따릅니다.
|연결| 그리고 |업그레이드| 헤더 필드는 HTTP 업그레이드를 완료합니다. |Sec-WebSocket-Accept| 헤더 필드는 서버가 연결을 수락할지 여부를 나타냅니다. 있는 경우 이 헤더 필드에는 |Sec-WebSocket-Key|에서 전송된 클라이언트 nonce의 해시가 포함되어야 합니다. 사전 정의된 GUID와 함께. 다른 값은 서버의 연결 승인으로 해석되어서는 안 됩니다.
```text
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
```
이 필드는 스크립트된 페이지에 대해 WebSocket 클라이언트에서 확인됩니다. |Sec-WebSocket-Accept| 값이 예상 값과 일치하지 않거나 헤더 필드가 누락되거나 HTTP 상태 코드가 101이 아닌 경우 연결이 설정되지 않으며 WebSocket 프레임이 전송되지 않습니다.
옵션 필드도 포함될 수 있습니다. 이 버전의 프로토콜에서 기본 옵션 필드는 |Sec-WebSocket-Protocol|이며, 이는 서버가 선택한 하위 프로토콜을 나타냅니다. WebSocket 클라이언트는 WebSocket 클라이언트의 핸드셰이크에 지정된 값 중 하나가 서버에 포함되어 있는지 확인합니다. 여러 하위 프로토콜을 사용하는 서버는 클라이언트의 핸드셰이크를 기반으로 하위 프로토콜을 선택하고 이를 핸드셰이크에서 지정하는지 확인해야 합니다.
```text
Sec-WebSocket-Protocol: chat
```
서버는 \[RFC6265\]에 설명된 대로 쿠키 관련 옵션 필드를 \_set\_cookies로 설정할 수도 있습니다.
---
### **1.4. Closing Handshake**
\_이 섹션은 비표준 섹션입니다.\_
닫는 악수는 여는 악수보다 훨씬 간단합니다.
각 피어는 지정된 제어 시퀀스가 포함된 데이터와 함께 제어 프레임을 보내 닫는 핸드셰이크를 시작할 수 있습니다\(자세한 내용은 섹션 5.5.1 참조\). 이러한 프레임을 수신하면 다른 피어는 아직 Close 프레임을 보내지 않은 경우 이에 대한 응답으로 Close 프레임을 보냅니다. \_해당\_ 제어 프레임을 수신하면 첫 번째 피어는 더 이상 데이터가 나오지 않는다는 사실을 알고 연결을 닫습니다.
연결을 닫아야 함을 나타내는 제어 프레임을 보낸 후 피어는 더 이상 데이터를 보내지 않습니다. 연결을 닫아야 함을 나타내는 제어 프레임을 수신한 후 피어는 수신된 추가 데이터를 삭제합니다.
두 피어가 동시에 이 핸드셰이크를 시작하는 것이 안전합니다.
닫는 핸드셰이크는 TCP 닫는 핸드셰이크\(FIN/ACK\)를 보완하기 위한 것입니다. 특히, 가로채는 프록시 및 기타 중개자가 있는 경우 TCP 닫는 핸드셰이크가 항상 종단 간 신뢰할 수 있는 것은 아니라는 점을 기반으로 합니다.
닫기 프레임을 보내고 응답으로 닫기 프레임을 기다리면 데이터가 불필요하게 손실될 수 있는 특정 상황을 피할 수 있습니다. 예를 들어, 일부 플랫폼에서는 수신 큐에 데이터가 있는 소켓이 닫히면 RST 패킷이 전송됩니다. 그러면 대기 중인 데이터가 있더라도 RST를 수신한 당사자에 대해 recv\(\)가 실패하게 됩니다. 읽다.
---
### **1.5. Design Philosophy**
\_이 섹션은 비표준 섹션입니다.\_
WebSocket 프로토콜은 최소한의 프레이밍이 있어야 한다는 원칙에 따라 설계되었습니다\(존재하는 유일한 프레이밍은 프로토콜을 스트림 기반이 아닌 프레임 기반으로 만들고 유니코드 텍스트와 바이너리 프레임 간의 구별을 지원하는 것입니다\). 메타데이터는 애플리케이션에 의해 WebSocket 위에 계층화될 것으로 예상됩니다.
메타데이터가 애플리케이션 계층\(예: HTTP\)에 의해 TCP 위에 계층화되는 것과 같은 방식으로 계층.
개념적으로 WebSocket은 실제로 다음을 수행하는 TCP 위에 있는 계층입니다.
o 브라우저에 웹 출처 기반 보안 모델을 추가합니다.
o 하나의 포트에서 여러 서비스를 지원하고 하나의 IP 주소에서 여러 호스트 이름을 지원하는 주소 지정 및 프로토콜 명명 메커니즘을 추가합니다.
o TCP 위에 프레이밍 메커니즘을 계층화하여 TCP가 구축된 IP 패킷 메커니즘으로 돌아가지만 길이 제한은 없습니다.
o 프록시 및 기타 중개자가 있는 경우 작동하도록 설계된 추가 폐쇄 핸드셰이크를 대역 내에서 포함합니다.
그 외에 WebSocket은 아무것도 추가하지 않습니다. 기본적으로 이는 웹의 제약 조건을 고려하여 원시 TCP를 스크립트에 최대한 노출시키는 것과 비슷하도록 의도되었습니다. 또한 핸드셰이크가 유효한 HTTP 업그레이드 요청이 되도록 하여 서버가 HTTP 서버와 포트를 공유할 수 있도록 설계되었습니다. 개념적으로 다른 프로토콜을 사용하여 클라이언트-서버 메시징을 설정할 수 있지만 WebSocket의 목적은 HTTP 및 배포된 HTTP 인프라\(예: 프록시\)와 공존할 수 있고 TCP에 최대한 가까운 비교적 간단한 프로토콜을 제공하는 것입니다. 보안을 고려한 인프라와 함께 사용하고, 사용을 단순화하고 간단한 작업을 단순하게 유지하기 위한 추가 기능\(예: 메시지 의미 추가\)을 사용합니다.
프로토콜은 확장 가능하도록 고안되었습니다. 향후 버전에서는 멀티플렉싱과 같은 추가 개념이 도입될 가능성이 높습니다.
---
### **1.6. Security Model**
\_이 섹션은 비표준 섹션입니다.\_
WebSocket 프로토콜은 웹 브라우저에서 사용하는 원본 모델을 사용하여 WebSocket 프로토콜이 웹 페이지에서 사용될 때 WebSocket 서버에 접속할 수 있는 웹 페이지를 제한합니다. 당연히 WebSocket 프로토콜이 전용 클라이언트에 의해 직접 사용되는 경우\(즉, 웹 브라우저를 통한 웹 페이지가 아닌\) 클라이언트가 임의의 원본 문자열을 제공할 수 있으므로 원본 모델은 유용하지 않습니다.
이 프로토콜은 SMTP \[RFC5321\] 및 HTTP와 같은 기존 프로토콜의 서버와의 연결을 설정하지 못하도록 고안되었으며, 다음과 같은 경우 HTTP 서버가 이 프로토콜을 지원하도록 옵트인할 수 있습니다.
원하는. 이는 엄격하고 정교한 핸드셰이크를 사용하고 핸드셰이크가 완료되기 전에 연결에 삽입할 수 있는 데이터를 제한함으로써 달성됩니다\(따라서 서버가 영향을 받을 수 있는 정도를 제한함\).
예를 들어 HTML "양식"이 WebSocket 서버에 제출된 경우 발생할 수 있는 것처럼 다른 프로토콜, 특히 HTTP의 데이터가 WebSocket 서버로 전송될 때 연결 설정에 실패하는 것과 유사합니다. 이는 주로 서버가 핸드셰이크를 읽었음을 증명하도록 요구함으로써 달성됩니다. 이는 핸드셰이크에 WebSocket 클라이언트에 의해서만 전송될 수 있는 적절한 부분이 포함된 경우에만 수행할 수 있습니다. 특히, 이 사양을 작성하는 시점에는 |Sec-|로 시작하는 필드가 있습니다. 공격자는 XMLHttpRequest \[XMLHttpRequest\]와 같은 HTML 및 JavaScript API만 사용하여 웹 브라우저에서 설정할 수 없습니다.
---
### **1.7. Relationship to TCP and HTTP**
\_이 섹션은 비표준 섹션입니다.\_
WebSocket 프로토콜은 독립적인 TCP 기반 프로토콜입니다. HTTP와의 유일한 관계는 핸드셰이크가 HTTP 서버에 의해 업그레이드 요청으로 해석된다는 것입니다.
기본적으로 WebSocket 프로토콜은 일반 WebSocket 연결에 포트 80을 사용하고 TLS\(전송 계층 보안\) \[RFC2818\]를 통해 터널링되는 WebSocket 연결에 포트 443을 사용합니다.
---
### **1.8. Establishing a Connection**
\_이 섹션은 비표준 섹션입니다.\_
HTTP 서버가 공유하는 포트에 연결이 이루어지면\(포트 80 및 443에 대한 트래픽에서 발생할 가능성이 매우 높은 상황\) 연결은 HTTP 서버에 다음과 같은 일반 GET 요청으로 나타납니다. 업그레이드 제안. 단 하나의 IP 주소와 단일 호스트 이름에 대한 모든 트래픽을 위한 단일 서버를 사용하는 비교적 간단한 설정에서는 WebSocket 프로토콜 기반 시스템을 배포할 수 있는 실용적인 방법이 될 수 있습니다. 보다 정교한 설정\(예: 로드 밸런서 및 여러 서버 포함\)에서는 HTTP 서버와 별도로 WebSocket 연결을 위한 전용 호스트 세트를 관리하는 것이 더 쉬울 것입니다. 이 사양을 작성할 당시에는 포트 80과 443의 연결 성공률이 크게 다르며, 포트 443의 연결이 성공할 가능성이 훨씬 더 높지만 이는 시간이 지남에 따라 바뀔 수 있습니다.
---
### **1.9. Subprotocols Using the WebSocket Protocol**
\_이 섹션은 비표준 섹션입니다.\_
클라이언트는 |Sec-WebSocket-Protocol|을 포함하여 서버가 특정 하위 프로토콜을 사용하도록 요청할 수 있습니다. 핸드셰이크의 필드입니다. 지정된 경우 서버는 연결 설정에 대한 응답에 동일한 필드와 선택한 하위 프로토콜 값 중 하나를 포함해야 합니다.
이러한 하위 프로토콜 이름은 섹션 11.5에 따라 등록되어야 합니다. 잠재적인 충돌을 방지하려면 하위 프로토콜 발신자의 도메인 이름의 ASCII 버전이 포함된 이름을 사용하는 것이 좋습니다. 예를 들어, example Corporation이 웹상의 많은 서버에서 구현할 Chat 하위 프로토콜을 생성한다면 이름을 "chat.example.com"으로 지정할 수 있습니다. 예시 조직이 경쟁 하위 프로토콜 "chat.example.org"를 호출한 경우 두 개의 하위 프로토콜은 서버에 의해 동시에 구현될 수 있으며, 서버는 클라이언트가 보낸 값을 기반으로 사용할 하위 프로토콜을 동적으로 선택합니다.
하위 프로토콜 이름을 변경하여\(예: "bookings.example.net"에서 "v2.bookings.example.net"으로 변경\) 하위 프로토콜은 이전 버전과 호환되지 않는 방식으로 버전을 관리할 수 있습니다. 이러한 하위 프로토콜은 WebSocket 클라이언트에 의해 완전히 별개로 간주됩니다. 동일한 하위 프로토콜 문자열을 재사용하지만 이러한 종류의 확장성을 지원하도록 실제 하위 프로토콜을 신중하게 설계하면 이전 버전과 호환되는 버전 관리를 구현할 수 있습니다.
---
## **2. Conformance Requirements**
이 사양의 모든 다이어그램, 예제 및 참고 사항은 비표준으로 명시적으로 표시된 모든 섹션과 마찬가지로 비표준입니다. 이 사양의 다른 모든 내용은 규범적입니다.
이 문서에서 키워드 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" 및 "OPTIONAL"은 다음과 같습니다. \[RFC2119\]에 설명된 대로 해석됩니다.\(MUST NOT\)
알고리즘의 일부로 명령형으로 표현된 요구 사항\(예: "모든 선행 공백 문자 제거" 또는 "false를 반환하고 이 단계를 중단"\)은 핵심 단어\("MUST", "SHOULD", " MAY" 등\)을 알고리즘 도입에 사용합니다.\(MUST\)
알고리즘이나 특정 단계로 표현된 적합성 요구 사항은 최종 결과가 동일하다면 어떤 방식으로든 구현될 수 있습니다. \(특히, 본 명세서에 정의된 알고리즘은 따르기 쉽도록 의도된 것이지 성능을 높이려는 의도는 아니다.\)\(MAY\)
---
### **2.1. Terminology and Other Conventions**
\_ASCII\_는 \[ANSI.X3-4.1986\]에 정의된 문자 인코딩 체계를 의미합니다.
이 문서는 UTF-8 값을 참조하고 STD 63 \[RFC3629\]에 정의된 UTF-8 표기 형식을 사용합니다.
명명된 알고리즘이나 정의와 같은 주요 용어는 \_this\_처럼 표시됩니다.
```text
Names of header fields or variables are indicated like |this|.
Variable values are indicated like /this/.
```
이 문서에서는 \_WebSocket 연결 실패\_ 절차를 참조합니다. 이 절차는 섹션 7.1.7에 정의되어 있습니다.
\_문자열을 ASCII 소문자로 변환\_한다는 것은 U+0041 \~ U+005A 범위\(예: LATIN CAPITAL LETTER A \~ LATIN CAPITAL LETTER Z\)의 모든 문자를 U+0061 \~ U+007A 범위의 해당 문자\(예: 라틴 소문자 A \~ 라틴 소문자 Z\).
\_ASCII 대소문자를 구분하지 않는 방식으로 두 문자열을 비교한다는 것은 U+0041 \~ U+005A 범위의 문자\(예: LATIN CAPITAL LETTER A \~ LATIN CAPITAL LETTER Z\)와 U+0061 \~ U+007A 범위의 해당 문자\(예: LATIN SMALL LETTER A \~ LATIN SMALL LETTER Z\)도 일치하는 것으로 간주됩니다.
"URI"라는 용어는 \[RFC3986\]에 정의된 대로 이 문서에서 사용됩니다.
구현이 WebSocket 프로토콜의 일부로 데이터를 \_전송\_해야 하는 경우 구현은 실제 전송을 임의로 지연시킬 수 있습니다\(예: 더 적은 수의 IP 패킷을 전송하기 위해 데이터를 버퍼링\).\(MAY\)
이 문서는 서로 다른 섹션에서 ABNF의 \[RFC5234\] 및 \[RFC2616\] 변형을 모두 사용합니다.
---
## **3. WebSocket URIs**
이 사양은 RFC 5234 \[RFC5234\]에 정의된 ABNF 구문과 URI 사양 RFC 3986 \[RFC3986\]에 정의된 용어 및 ABNF 생성을 사용하여 두 가지 URI 체계를 정의합니다.
```text
ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
host = <host, defined in [RFC3986], Section 3.2.2>
port = <port, defined in [RFC3986], Section 3.2.3>
path = <path-abempty, defined in [RFC3986], Section 3.3>
query = <query, defined in [RFC3986], Section 3.4>
```
포트 구성 요소는 선택 사항입니다. "ws"의 기본값은 포트 80이고 "wss"의 기본값은 포트 443입니다.\(MAY\)
스키마 구성요소가 대소문자를 구분하지 않고 "wss"와 일치하는 경우 URI는 "보안"이라고 합니다\("보안 플래그가 설정됨"이라고 함\).
"resource-name"\(섹션 4.1에서는 /resource name/이라고도 함\)은 다음을 연결하여 구성할 수 있습니다.
o 경로 구성 요소가 비어 있으면 "/"
o 경로 구성요소
아 "?" 쿼리 구성 요소가 비어 있지 않은 경우
o 쿼리 구성요소
조각 식별자는 WebSocket URI의 컨텍스트에서는 의미가 없으며 이러한 URI에 사용되어서는 안 됩니다. 다른 URI 체계와 마찬가지로 문자 "#"은 조각의 시작을 나타내지 않을 때 %23으로 이스케이프되어야 합니다.\(MUST NOT, MUST\)
---
## **4. Opening Handshake**
---
### **4.1. Client Requirements**
```text
To _Establish a WebSocket Connection_, a client opens a connection
and sends a handshake as defined in this section. A connection is
defined to initially be in a CONNECTING state. A client will need to
supply a /host/, /port/, /resource name/, and a /secure/ flag, which
are the components of a WebSocket URI as discussed in Section 3,
along with a list of /protocols/ and /extensions/ to be used.
Additionally, if the client is a web browser, it supplies /origin/.
```
통제된 환경\(예: 특정 통신업체에 연결된 모바일 핸드셋의 브라우저\)에서 실행되는 클라이언트는 연결 관리를 네트워크의 다른 에이전트에 오프로드할 수 있습니다. 이러한 상황에서 이 사양의 목적에 따라 클라이언트는 핸드셋 소프트웨어와 해당 에이전트를 모두 포함하는 것으로 간주됩니다.\(MAY\)
클라이언트가 사용할 /protocols/ 및 /extensions/ 목록과 함께 \(/host/, /port/, /resource name/ 및 /secure/ 플래그\) 세트가 제공되어 \_WebSocket 연결을 설정\_하려는 경우, 웹 브라우저의 경우 /origin/은 연결을 열고 오프닝 핸드셰이크를 보내고 이에 대한 응답으로 서버의 핸드셰이크를 읽어야 합니다. 연결을 열어야 하는 방법, 핸드셰이크를 시작할 때 무엇을 보내야 하는지, 서버의 응답을 어떻게 해석해야 하는지에 대한 정확한 요구 사항은 이 섹션에서 다음과 같습니다. 다음 텍스트에서는 해당 섹션에 정의된 "/host/" 및 "/secure/flag"와 같은 섹션 3의 용어를 사용합니다.\(MUST\)
1. 이 알고리즘에 전달된 WebSocket URI의 구성 요소\(/host/, /port/, /resource name/ 및 /secure/ 플래그\)는 섹션 3에 지정된 WebSocket URI 사양에 따라 유효해야 합니다. 구성 요소가 유효하지 않은 경우 클라이언트는 반드시 \_WebSocket 연결에 실패\_하고 이 단계를 중단해야 합니다.\(MUST, MUST\)
2. 클라이언트가 이미 /host/ 및 포트 /port/ 쌍으로 식별되는 원격 호스트\(IP 주소\)에 대한 WebSocket 연결을 갖고 있는 경우, 원격 호스트가 다른 이름으로 알려지더라도 클라이언트는 해당 연결이 완료될 때까지 기다려야 합니다. 설정되었거나 해당 연결이 실패했습니다. CONNECTING 상태에는 연결이 하나만 있어야 합니다. 동일한 IP 주소에 대한 여러 연결이 동시에 시도되는 경우 클라이언트는 다음 단계를 통해 한 번에 하나 이상의 연결이 실행되지 않도록 연결을 직렬화해야 합니다.\(MUST, MUST, MUST\)
- 클라이언트가 원격 호스트의 IP 주소를 확인할 수 없는 경우\(예: 모든 통신이 DNS 쿼리 자체를 수행하는 프록시 서버를 통해 수행되기 때문에\) 클라이언트는 이 단계의 목적을 위해 각 호스트 이름이 참조하는 것으로 가정해야 합니다. 대신 클라이언트는 동시에 보류 중인 연결의 총 수를 합리적으로 낮은 수로 제한해야 합니다\(예: 클라이언트는 a.example.com 및 b.example.com에 대한 동시 보류 연결을 허용할 수 있지만 30개인 경우\). 단일 호스트에 대한 동시 연결이 요청되지만 이는 허용되지 않을 수 있습니다.\) 예를 들어, 웹 브라우저 컨텍스트에서 클라이언트는 동시에 보류 중인 연결 수에 대한 제한을 설정할 때 사용자가 열어 놓은 탭 수를 고려해야 합니다.\(MUST\)
- 참고: 이렇게 하면 스크립트가 원격 호스트에 대한 많은 수의 WebSocket 연결을 열어 서비스 거부 공격을 수행하기가 더 어려워집니다. 서버는 연결을 닫기 전에 일시 중지하여 공격을 받을 때 클라이언트가 다시 연결하는 속도를 줄이므로 자체 부하를 더욱 줄일 수 있습니다.
- 참고: 클라이언트가 단일 원격 호스트와 가질 수 있는 설정된 WebSocket 연결 수에는 제한이 없습니다. 서버는 기존 연결 수가 너무 많은 호스트/IP 주소로부터의 연결 수락을 거부하거나 부하가 높을 때 리소스를 많이 차지하는 연결을 끊을 수 있습니다.
```text
3. _Proxy Usage_: If the client is configured to use a proxy when
using the WebSocket Protocol to connect to host /host/ and port
/port/, then the client SHOULD connect to that proxy and ask it
to open a TCP connection to the host given by /host/ and the port
given by /port/.
```
- 예: 예를 들어 클라이언트가 모든 트래픽에 대해 HTTP 프록시를 사용하는 경우 example.com 서버의 포트 80에 연결을 시도하면 다음 줄을 프록시 서버로 보낼 수 있습니다.
```text
CONNECT example.com:80 HTTP/1.1
Host: example.com
```
- 비밀번호가 있는 경우 연결은 다음과 같습니다.
```text
CONNECT example.com:80 HTTP/1.1
Host: example.com
Proxy-authorization: Basic ZWRuYW1vZGU6bm9jYXBlcyE=
If the client is not configured to use a proxy, then a direct TCP
connection SHOULD be opened to the host given by /host/ and the
port given by /port/.
```
참고: 명시적인 UI를 노출하지 않는 구현은
- 다른 프록시와 별도로 WebSocket 연결을 위한 프록시 선택은 가능하다면 WebSocket 연결을 위해 SOCKS5 \[RFC1928\] 프록시를 사용하는 것이 좋습니다. 그렇지 않으면 HTTP 연결용으로 구성된 프록시보다 HTTPS 연결용으로 구성된 프록시를 선호합니다.
- 프록시 자동 구성 스크립트의 목적을 위해 함수를 전달하는 URI는 섹션 3에 제공된 WebSocket URI의 정의를 사용하여 /host/, /port/, /resource name/ 및 /secure/ 플래그에서 구성되어야 합니다. .\(MUST\)
참고: WebSocket 프로토콜은 프록시에서 식별될 수 있습니다.
- 구성표의 자동 구성 스크립트\(암호화되지 않은 연결의 경우 "ws", 암호화된 연결의 경우 "wss"\).
4. 직접 연결이 실패했거나 사용된 프록시가 오류를 반환하여 연결을 열 수 없는 경우 클라이언트는 반드시 \_WebSocket 연결 실패\_ 및 연결 시도를 중단해야 합니다.\(MUST\)
5. /secure/가 true인 경우 클라이언트는 연결을 연 후 핸드셰이크 데이터\[RFC2818\]를 전송하기 전에 연결을 통해 TLS 핸드셰이크를 수행해야 합니다. 이것이 실패하는 경우\(예: 서버의 인증서를 확인할 수 없는 경우\) 클라이언트는 반드시 \_WebSocket 연결에 실패\_하고 연결을 중단해야 합니다. 그렇지 않으면 이 채널의 모든 추가 통신은 암호화된 터널\[RFC5246\]을 통해 실행되어야 합니다.\(MUST, MUST, MUST\)
- 클라이언트는 TLS 핸드셰이크 \[RFC6066\]에서 서버 이름 표시 확장을 사용해야 합니다.\(MUST\)
서버에 대한 연결이 설정되면\(프록시 또는 TLS 암호화 터널을 통한 연결 포함\) 클라이언트는 오프닝 핸드셰이크를 서버에 보내야 합니다. 핸드셰이크는 필수 및 선택적 헤더 필드 목록과 함께 HTTP 업그레이드 요청으로 구성됩니다. 이 핸드셰이크의 요구 사항은 다음과 같습니다.\(MUST\)
1. 핸드셰이크는 \[RFC2616\]에 지정된 대로 유효한 HTTP 요청이어야 합니다.\(MUST\)
2. 요청 방법은 GET이어야 하며, HTTP 버전은 1.1 이상이어야 합니다.\(MUST\)
- 예를 들어 WebSocket URI가 "ws://example.com/chat"인 경우 전송되는 첫 번째 줄은 "GET /chat HTTP/1.1"이어야 합니다.
3. 요청의 "요청-URI" 부분은 섹션 3\(상대 URI\)에 정의된 /resource name/과 일치하거나 구문 분석 시 /resource name/, /host를 갖는 절대 http/https URI여야 합니다. / 및 /port/는 해당 ws/wss URI와 일치합니다.\(MUST\)
4. 요청에는 |Host|가 포함되어야 합니다. 값에 /host/와 선택적으로 ":" 다음에 /port/가 포함되는 헤더 필드\(기본 포트를 사용하지 않는 경우\)\(MUST\)
5. 요청에는 |Upgrade|가 포함되어야 합니다. 값이 "websocket" 키워드를 포함해야 하는 헤더 필드입니다.\(MUST\)
6. 요청에는 |Connection|이 포함되어야 합니다. 값이 "업그레이드" 토큰을 포함해야 하는 헤더 필드입니다.\(MUST\)
7. 요청에는 이름이 포함된 헤더 필드가 포함되어야 합니다.
- |Sec-WebSocket-Key|. 이 헤더 필드의 값은 base64로 인코딩된 무작위로 선택된 16바이트 값으로 구성된 nonce여야 합니다\(\[RFC4648\]의 섹션 4 참조\). nonce는 각 연결에 대해 무작위로 선택되어야 합니다.\(MUST, MUST, MUST\)
```text
NOTE: As an example, if the randomly selected value was the
sequence of bytes 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, the value of the header
field would be "AQIDBAUGBwgJCgsMDQ4PEC=="
```
8. 요청에는 |Origin|이라는 이름의 헤더 필드가 포함되어야 합니다. \[RFC6454\] 요청이 브라우저 클라이언트에서 오는 경우. 연결이 브라우저가 아닌 클라이언트에서 오는 경우 해당 클라이언트의 의미가 브라우저 클라이언트에 대해 여기에 설명된 사용 사례와 일치하면 요청에 이 헤더 필드가 포함될 수 있습니다. 이 헤더 필드의 값은 연결을 설정하는 코드가 실행되는 컨텍스트의 원본에 대한 ASCII 직렬화입니다. 이 헤더 필드 값이 구성되는 방법에 대한 자세한 내용은 \[RFC6454\]를 참조하세요.\(MUST, MAY\)
- 예를 들어, www.example.com에서 다운로드한 코드가 ww2.example.com에 대한 연결 설정을 시도하는 경우 헤더 필드의 값은 "http://www.example.com"이 됩니다.
9. 요청에는 이름이 포함된 헤더 필드가 포함되어야 합니다.
- |Sec-WebSocket-버전|. 이 헤더 필드의 값은 13이어야 합니다.\(MUST, MUST\)
- 참고: 이 문서의 초안 버전\(-09, -10, -11 및 -12\)이 게시되었지만\(대부분 편집 변경 사항 및 설명으로 구성되었으며 유선 프로토콜 변경 사항은 아님\) 값은 9, 10, 11입니다. 및 12는 Sec-WebSocket-Version의 유효한 값으로 사용되지 않았습니다. 이러한 값은 IANA 레지스트리에 예약되어 있었지만 사용되지 않았으며 앞으로도 사용되지 않을 것입니다.
10. 요청에는 이름이 포함된 헤더 필드가 포함될 수 있습니다.
- |Sec-WebSocket-프로토콜|. 존재하는 경우 이 값은 클라이언트가 말하고 싶어하는 하나 이상의 쉼표로 구분된 하위 프로토콜을 나타내며 기본 설정에 따라 정렬됩니다. 이 값을 구성하는 요소는 \[RFC2616\]에 정의된 구분 문자를 포함하지 않는 U+0021 \~ U+007E 범위의 문자가 포함된 비어 있지 않은 문자열이어야 하며 모두 고유한 문자열이어야 합니다. 이 헤더 필드 값의 ABNF는 1#token이며, 여기서 구성 및 규칙의 정의는 \[RFC2616\]에 나와 있습니다.\(MAY, MUST\)
11. 요청에는 이름이 포함된 헤더 필드가 포함될 수 있습니다.
- |Sec-WebSocket-Extensions|. 존재하는 경우 이 값은 클라이언트가 말하고자 하는 프로토콜 수준 확장을 나타냅니다. 이 헤더 필드의 해석과 형식은 섹션 9.1에 설명되어 있습니다.\(MAY\)
12. 요청에는 쿠키 \[RFC6265\] 및/또는 |Authorization|과 같은 인증 관련 헤더 필드와 같은 다른 헤더 필드가 포함될 수 있습니다. 헤더 필드 \[RFC2616\]는 이를 정의하는 문서에 따라 처리됩니다.\(MAY\)
클라이언트의 오프닝 핸드셰이크가 전송되면 클라이언트는 추가 데이터를 보내기 전에 서버의 응답을 기다려야 합니다. 클라이언트는 다음과 같이 서버의 응답을 검증해야 합니다.\(MUST, MUST\)
1. 서버로부터 수신한 상태 코드가 101이 아닌 경우 클라이언트는 HTTP \[RFC2616\] 절차에 따라 응답을 처리합니다. 특히 클라이언트는 401 상태 코드를 수신하면 인증을 수행할 수 있습니다. 서버는 3xx 상태 코드를 사용하여 클라이언트를 리디렉션할 수 있습니다\(그러나 클라이언트는 이를 따를 필요가 없습니다\). 그렇지 않으면 다음과 같이 진행하십시오.
2. 응답에 |Upgrade|가 없는 경우 헤더 필드 또는 |Upgrade| 헤더 필드에 "websocket" 값과 일치하는 ASCII 대소문자 구분이 아닌 값이 포함되어 있으면 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
3. 응답에 |Connection|이 없는 경우 헤더 필드 또는
- |연결| 헤더 필드에 "Upgrade" 값과 일치하는 ASCII 대소문자를 구분하지 않는 토큰이 포함되어 있지 않으면 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
4. 응답에 |Sec-WebSocket-Accept|가 없는 경우 헤더 필드 또는 |Sec-WebSocket-Accept| |Sec-WebSocket-Key| 연결의 base64 인코딩 SHA-1 이외의 값이 포함되어 있습니다. \(base64로 디코딩되지 않은 문자열로\) 문자열 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"을 포함하지만 선행 및 후행 공백을 무시하면 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
5. 응답에 |Sec-WebSocket-Extensions| 헤더 필드와 이 헤더 필드는 클라이언트의 핸드셰이크에 존재하지 않는 확장의 사용을 나타냅니다\(서버는 클라이언트가 요청하지 않은 확장을 나타냄\). 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다. \(어떤 확장이 요청되는지 결정하기 위한 이 헤더 필드의 구문 분석은 섹션 9.1에서 논의됩니다.\)\(MUST\)
6. 응답에 |Sec-WebSocket-Protocol| 헤더 필드와 이 헤더 필드는 클라이언트의 핸드셰이크에 존재하지 않는 하위 프로토콜의 사용을 나타냅니다\(서버는 클라이언트가 요청하지 않은 하위 프로토콜을 나타냄\). 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
서버의 응답이 이 섹션과 섹션 4.2.2에 정의된 서버 핸드셰이크 요구 사항을 준수하지 않는 경우 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
\[RFC2616\]에 따르면 HTTP 요청과 HTTP 응답 모두의 모든 헤더 필드 이름은 대소문자를 구분하지 않습니다.
위와 같이 서버의 응답이 검증되면 \_WebSocket 연결이 설정됨\_이며 WebSocket 연결이 OPEN 상태라고 합니다. \_Extensions In Use\_는 \(아마도 비어 있는\) 문자열로 정의되며 그 값은 |Sec-WebSocket-Extensions| 서버의 핸드셰이크에 의해 제공된 헤더 필드 또는 해당 헤더 필드가 서버의 핸드셰이크에 없는 경우 null 값입니다. \_Subprotocol In Use\_는 |Sec-WebSocket-Protocol|의 값으로 정의됩니다. 서버 핸드셰이크의 헤더 필드 또는 해당 헤더 필드가 서버 핸드셰이크에 없는 경우 null 값입니다. 또한 서버 핸드셰이크의 헤더 필드에 쿠키가 설정되어야 함을 나타내는 경우\(\[RFC6265\]에 정의된 대로\) 이러한 쿠키는 \_서버의 오프닝 핸드셰이크 동안 설정된 쿠키\_라고 합니다.
---
### **4.2. Server-Side Requirements**
서버는 연결 관리를 네트워크의 다른 에이전트\(예: 로드 밸런서 및 역방향 프록시\)에 오프로드할 수 있습니다. 이러한 상황에서 본 사양의 목적에 따라 서버는 TCP 연결을 종료하는 첫 번째 장치부터 요청을 처리하고 응답을 보내는 서버까지 서버 측 인프라의 모든 부분을 포함하는 것으로 간주됩니다.\(MAY\)
예: 데이터 센터에는 적절한 핸드셰이크를 통해 WebSocket 요청에 응답한 다음 연결을 다른 서버에 전달하여 실제로 데이터 프레임을 처리하는 서버가 있을 수 있습니다. 이 사양의 목적에 따라 "서버"는 두 컴퓨터의 조합입니다.
---
#### **4.2.1. Reading the Client's Opening Handshake**
클라이언트가 WebSocket 연결을 시작하면 시작 핸드셰이크의 일부를 보냅니다. 서버는 핸드셰이크의 서버 부분을 생성하는 데 필요한 정보를 얻기 위해 이 핸드셰이크의 적어도 일부를 구문 분석해야 합니다.
클라이언트의 오프닝 핸드셰이크는 다음 부분으로 구성됩니다. 서버가 핸드셰이크를 읽는 동안 클라이언트가 위반 사항을 포함하되 이에 국한되지 않는 아래 설명과 일치하는 핸드셰이크를 보내지 않았음을 발견한 경우\(\[RFC2616\]에 따라 헤더 필드의 순서는 중요하지 않음\) 핸드셰이크 구성 요소에 대해 지정된 ABNF 문법에 따라 서버는 클라이언트의 핸드셰이크 처리를 중지하고 적절한 오류 코드\(예: 400 잘못된 요청\)와 함께 HTTP 응답을 반환해야 합니다.\(MUST\)
1. 섹션 3에 정의된 /resource name/\(또는 /resource name/을 포함하는 절대 HTTP/HTTPS URI\)으로 해석되어야 하는 "Request-URI" \[RFC2616\]를 포함한 HTTP/1.1 이상의 GET 요청 .
2. A |호스트| 서버의 권한을 포함하는 헤더 필드입니다.
3. |업그레이드| "websocket" 값을 포함하는 헤더 필드는 ASCII 대소문자를 구분하지 않는 값으로 처리됩니다.
4. A |연결| "Upgrade" 토큰을 포함하는 헤더 필드는 ASCII 대소문자를 구분하지 않는 값으로 처리됩니다.
5. A |Sec-WebSocket-Key| 디코딩 시 길이가 16바이트인 base64로 인코딩된\(\[RFC4648\]의 섹션 4 참조\) 값이 있는 헤더 필드입니다.
6. A |Sec-WebSocket-버전| 값이 13인 헤더 필드입니다.
7. 선택적으로 |Origin| 헤더 필드. 이 헤더 필드는 모든 브라우저 클라이언트에서 전송됩니다. 이 헤더 필드가 없는 연결 시도는 브라우저 클라이언트에서 오는 것으로 해석되어서는 안 됩니다.\(SHOULD NOT\)
8. 선택적으로 |Sec-WebSocket-Protocol| 클라이언트가 어떤 프로토콜을 말하고 싶은지 나타내는 값 목록이 있는 헤더 필드. 선호도에 따라 정렬됩니다.
9. 선택적으로 |Sec-WebSocket-Extensions| 클라이언트가 말하고 싶어하는 확장을 나타내는 값 목록이 있는 헤더 필드. 이 헤더 필드의 해석은 섹션 9.1에서 논의됩니다.
10. 선택적으로 쿠키를 보내거나 서버에 인증을 요청하는 데 사용되는 기타 헤더 필드. \[RFC2616\]에 따라 알 수 없는 헤더 필드는 무시됩니다.
---
#### **4.2.2. Sending the Server's Opening Handshake**
클라이언트가 서버에 대한 WebSocket 연결을 설정하면 서버는 연결을 수락하고 서버의 오프닝 핸드셰이크를 보내려면 다음 단계를 완료해야 합니다.\(MUST\)
1. 연결이 HTTPS\(HTTP-over-TLS\) 포트에서 발생하는 경우 연결을 통해 TLS 핸드셰이크를 수행합니다. 이것이 실패하면\(예를 들어 클라이언트가 서버가 호스팅하지 않는 확장 클라이언트 hello "server\_name" 확장에 호스트 이름을 표시한 경우\) 연결을 닫습니다. 그렇지 않으면 연결을 위한 모든 추가 통신\(서버의 핸드셰이크 포함\)이 암호화된 터널\[RFC5246\]을 통해 실행되어야 합니다.\(MUST\)
2. 서버는 예를 들어 해당 |WWW-Authenticate|와 함께 401 상태 코드를 반환하여 추가 클라이언트 인증을 수행할 수 있습니다. \[RFC2616\]에 설명된 헤더 필드입니다.
3. 서버는 3xx 상태 코드 \[RFC2616\]를 사용하여 클라이언트를 리디렉션할 수 있습니다. 이 단계는 위에서 설명한 선택적 인증 단계와 함께, 이전 또는 이후에 발생할 수 있습니다.\(MAY\)
4. 다음 정보를 설정합니다.
/기원/
- |원산지| 클라이언트 핸드셰이크의 헤더 필드는 연결을 설정하는 스크립트의 출처를 나타냅니다. 원점은 ASCII로 직렬화되어 소문자로 변환됩니다. 서버는 들어오는 연결을 수락할지 여부를 결정하는 과정의 일부로 이 정보를 사용할 수 있습니다. 서버가 원본의 유효성을 검사하지 않으면 어디에서든 연결을 수락합니다. 서버가 이 연결을 수락하지 않으려면 적절한 HTTP 오류 코드\(예: 403 Forbidden\)를 반환하고 이 섹션에 설명된 WebSocket 핸드셰이크를 중단해야 합니다. 자세한 내용은 섹션 10을 참조하세요.\(MAY, MUST\)
/열쇠/
- |Sec-WebSocket-Key| 클라이언트 핸드셰이크의 헤더 필드에는 base64로 인코딩된 값이 포함되어 있으며, 디코딩된 경우 길이는 16바이트입니다. 이\(인코딩된\) 값은 연결 승인을 나타내기 위해 서버의 핸드셰이크 생성에 사용됩니다. 서버가 |Sec-WebSocket-Key|를 base64로 디코딩할 필요는 없습니다. 값.
/버전/
- |Sec-WebSocket-Version| 클라이언트 핸드셰이크의 헤더 필드에는 클라이언트가 통신을 시도하는 WebSocket 프로토콜의 버전이 포함됩니다. 이 버전이 서버가 이해하는 버전과 일치하지 않으면 서버는 이 섹션에 설명된 WebSocket 핸드셰이크를 중단해야 하며 대신 적절한 HTTP 오류 코드\(예: 426 업그레이드 필요\)와 |Sec-WebSocket-Version| 서버가 이해할 수 있는 버전을 나타내는 헤더 필드입니다.\(MUST\)
/리소스 이름/
- 서버가 제공하는 서비스에 대한 식별자입니다. 서버가 여러 서비스를 제공하는 경우 GET 메서드의 "Request-URI" \[RFC2616\]에 있는 클라이언트 핸드셰이크에 제공된 리소스 이름에서 값을 파생해야 합니다. 요청된 서비스를 사용할 수 없는 경우 서버는 적절한 HTTP 오류 코드\(예: 404 찾을 수 없음\)를 전송하고 WebSocket 핸드셰이크를 중단해야 합니다.\(MUST\)
/서브프로토콜/
- 서버가 사용할 준비가 된 하위 프로토콜을 나타내는 단일 값이거나 null입니다. 선택한 값은 특히 |Sec-WebSocket-Protocol|에서 값 중 하나를 선택하여 클라이언트의 핸드셰이크에서 파생되어야 합니다. 서버가 이 연결에 사용할 의향이 있는 필드입니다\(있는 경우\). 클라이언트의 핸드셰이크에 그러한 헤더 필드가 포함되어 있지 않거나 서버가 클라이언트가 요청한 하위 프로토콜에 동의하지 않는 경우 허용되는 유일한 값은 null입니다. 이러한 필드가 없으면 null 값과 동일합니다. 즉, 서버가 제안된 하위 프로토콜 중 하나에 동의하지 않으려는 경우 응답으로 |Sec-WebSocket-Protocol| 헤더 필드를 다시 보내서는 안 됩니다. 빈 문자열은 이러한 목적을 위한 null 값과 동일하지 않으며 이 필드에 대한 유효한 값이 아닙니다. 이 헤더 필드의 값에 대한 ABNF는 \(token\)이며, 여기서 구성 및 규칙의 정의는 \[RFC2616\]에 나와 있습니다.\(MUST, MUST NOT\)
/확장자/
- 서버가 사용할 준비가 된 프로토콜 수준 확장을 나타내는 \(비어 있을 수도 있음\) 목록입니다. 서버가 여러 확장을 지원하는 경우 값은 특히 |Sec-WebSocket-Extensions|에서 하나 이상의 값을 선택하여 클라이언트의 핸드셰이크에서 파생되어야 합니다. 필드. 이러한 필드가 없으면 null 값과 같습니다. 빈 문자열은 이들에 대한 null 값과 동일하지 않습니다.\(MUST\)
- 목적. 클라이언트가 나열하지 않은 확장은 나열하면 안 됩니다. 이러한 값을 선택하고 해석하는 방법은 섹션 9.1에서 논의됩니다.\(MUST NOT\)
5. 서버가 들어오는 연결을 수락하기로 선택한 경우 다음을 나타내는 유효한 HTTP 응답으로 응답해야 합니다.\(MUST\)
- 1. RFC 2616 \[RFC2616\]에 따라 101 응답 코드가 있는 상태 줄. 이러한 응답은 "HTTP/1.1 101 Switching Protocols"처럼 보일 수 있습니다.
- 2. |업그레이드| RFC 2616 \[RFC2616\]에 따라 값이 "websocket"인 헤더 필드입니다.
- 3. A |연결| 값이 "업그레이드"인 헤더 필드입니다.
- 4. A |Sec-WebSocket-Accept| 헤더 필드. 이 헤더 필드의 값은 섹션 4.2.2의 4단계에서 정의된 /key/를 문자열 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"과 연결하여 이 연결된 값의 SHA-1 해시를 사용하여 구성됩니다. 20바이트 값과 이 20바이트 해시를 base64 인코딩\(\[RFC4648\]의 섹션 4 참조\)을 얻으려면
- 이 헤더 필드의 ABNF \[RFC2616\]은 다음과 같이 정의됩니다.
```text
Sec-WebSocket-Accept = base64-value-non-empty
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"
```
참고: 예를 들어, |Sec-WebSocket-Key| 클라이언트 핸드셰이크의 헤더 필드가 "dGhlIHNhbXBsZSBub25jZQ=="인 경우 서버는 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 문자열을 추가하여 "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC" 문자열을 구성합니다. 85B11". 그러면 서버는 이 문자열의 SHA-1 해시를 가져와 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea 값을 제공합니다. 그런 다음 이 값은 base64로 인코딩되어 "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=" 값을 제공하며, 이 값은 |Sec-WebSocket-Accept| 헤더 필드.
- 5. 선택적으로 |Sec-WebSocket-Protocol| 섹션 4.2.2의 4단계에 정의된 대로 /subprotocol/ 값을 갖는 헤더 필드.
- 6. 선택적으로 |Sec-WebSocket-Extensions| 섹션 4.2.2의 4단계에 정의된 대로 /extensions/ 값을 갖는 헤더 필드. 여러 확장을 사용하는 경우 단일 |Sec-WebSocket-Extensions|에 모두 나열할 수 있습니다. 헤더 필드 또는 |Sec-WebSocket-Extensions|의 여러 인스턴스 간에 분할됩니다. 헤더 필드.
이것으로 서버의 핸드셰이크가 완료됩니다. 서버가 WebSocket 핸드셰이크를 중단하지 않고 이러한 단계를 완료하면 서버는 WebSocket 연결이 설정되고 WebSocket 연결이 OPEN 상태인 것으로 간주합니다. 이 시점에서 서버는 데이터 보내기\(및 받기\)를 시작할 수 있습니다.
---
### **4.3. Collected ABNF for New Header Fields Used in Handshake**
이 섹션에서는 "묵시적 \*LWS 규칙"을 포함하여 \[RFC2616\] 섹션 2.1의 ABNF 구문/규칙을 사용합니다.
이 섹션에서는 다음 ABNF 규칙이 사용됩니다. 규칙의 일부 이름은 해당 헤더 필드의 이름에 해당합니다. 이러한 규칙은 해당 헤더 필드의 값을 표현합니다. 예를 들어 Sec-WebSocket-Key ABNF 규칙은 |Sec-WebSocket-Key|의 구문을 설명합니다. 헤더 필드 값. 이름에 "-Client" 접미사가 있는 ABNF 규칙은 클라이언트가 서버로 보낸 요청에만 사용됩니다. 이름에 "-Server" 접미사가 있는 ABNF 규칙은 서버에서 클라이언트로 보낸 응답에만 사용됩니다. 예를 들어, ABNF 규칙 Sec-WebSocket-Protocol-Client는 |Sec-WebSocket-Protocol|의 구문을 설명합니다. 클라이언트가 서버에 보낸 헤더 필드 값입니다.
클라이언트에서 서버로 핸드셰이크하는 동안 다음과 같은 새 헤더 필드가 전송될 수 있습니다.
```text
Sec-WebSocket-Key = base64-value-non-empty
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Protocol-Client = 1#token
Sec-WebSocket-Version-Client = version
base64-value-non-empty = (1*base64-data [ base64-padding ]) |
base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") |
(3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"
extension-list = 1#extension
extension = extension-token *( ";" extension-param )
extension-token = registered-token
registered-token = token
extension-param = token [ "=" (token | quoted-string) ]
; When using the quoted-string syntax variant, the value
; after quoted-string unescaping MUST conform to the
; 'token' ABNF.
NZDIGIT = "1" | "2" | "3" | "4" | "5" | "6" |
"7" | "8" | "9"
version = DIGIT | (NZDIGIT DIGIT) |
("1" DIGIT DIGIT) | ("2" DIGIT DIGIT)
; Limited to 0-255 range, with no leading zeros
```
서버에서 클라이언트로 핸드셰이크하는 동안 다음과 같은 새 헤더 필드가 전송될 수 있습니다.
```text
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Accept = base64-value-non-empty
Sec-WebSocket-Protocol-Server = token
Sec-WebSocket-Version-Server = 1#version
```
---
### **4.4. Supporting Multiple Versions of WebSocket Protocol**
이 섹션에서는 클라이언트와 서버에서 여러 버전의 WebSocket 프로토콜을 지원하는 방법에 대한 몇 가지 지침을 제공합니다.
WebSocket 버전 광고 기능\(|Sec-WebSocket-Version| 헤더 필드\)을 사용하여 클라이언트는 처음에 선호하는 WebSocket 프로토콜 버전을 요청할 수 있습니다\(반드시 클라이언트가 지원하는 최신 버전일 필요는 없음\). 서버가 요청한 버전을 지원하고 핸드셰이크 메시지가 유효한 경우 서버는 해당 버전을 수락합니다. 서버가 요청된 버전을 지원하지 않는 경우 |Sec-WebSocket-Version|으로 응답해야 합니다. 사용하려는 모든 버전을 포함하는 헤더 필드\(또는 여러 |Sec-WebSocket-Version| 헤더 필드\)입니다. 이 시점에서 클라이언트가 광고된 버전 중 하나를 지원하면 새 버전 값을 사용하여 WebSocket 핸드셰이크를 반복할 수 있습니다.\(MUST\)
다음 예에서는 위에서 설명한 버전 협상을 보여줍니다.
```text
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 25
```
서버의 응답은 다음과 같습니다.
```text
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13, 8, 7
```
서버의 마지막 응답은 다음과 같을 수도 있습니다.
```text
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13
Sec-WebSocket-Version: 8, 7
```
이제 클라이언트는 버전 13을 준수하는 핸드셰이크를 반복합니다.
```text
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 13
```
---
## **5. Data Framing**
---
### **5.1. Overview**
WebSocket 프로토콜에서 데이터는 일련의 프레임을 사용하여 전송됩니다. 네트워크 중개자\(예: 프록시 가로채기\)의 혼란을 방지하고 섹션 10.3에서 자세히 설명하는 보안상의 이유로 클라이언트는 서버에 보내는 모든 프레임을 마스크해야 합니다\(자세한 내용은 섹션 5.3 참조\). \(WebSocket 프로토콜이 TLS를 통해 실행 중인지 여부에 관계없이 마스킹이 수행됩니다.\) 서버는 마스킹되지 않은 프레임을 수신하면 연결을 닫아야 합니다. 이 경우 서버는 섹션 7.4.1에 정의된 대로 상태 코드 1002\(프로토콜 오류\)와 함께 닫기 프레임을 보낼 수 있습니다. 서버는 클라이언트에 전송하는 모든 프레임을 마스크해서는 안 됩니다. 클라이언트는 마스크된 프레임을 감지하면 연결을 닫아야 합니다. 이 경우 섹션 7.4.1에 정의된 대로 상태 코드 1002\(프로토콜 오류\)를 사용할 수 있습니다. \(이러한 규칙은 향후 사양에서 완화될 수 있습니다.\)\(MUST, MUST, MAY, MUST NOT, MUST, MAY\)
기본 프레이밍 프로토콜은 "페이로드 데이터"를 함께 정의하는 "확장 데이터" 및 "애플리케이션 데이터"에 대한 지정된 위치, opcode, 페이로드 길이를 사용하여 프레임 유형을 정의합니다. 특정 비트와 opcode는 향후 프로토콜 확장을 위해 예약되어 있습니다.
데이터 프레임은 핸드셰이크 열기가 완료된 후 해당 엔드포인트가 닫기 프레임\(섹션 5.5.1\)을 전송하기 전에 언제든지 클라이언트나 서버에 의해 전송될 수 있습니다.\(MAY\)
---
### **5.2. Base Framing Protocol**
데이터 전송 부분에 대한 이 와이어 형식은 이 섹션에 자세히 설명된 ABNF \[RFC5234\]에 설명되어 있습니다. \(이 문서의 다른 섹션과 달리 이 섹션의 ABNF는 비트 그룹에서 작동합니다. 각 비트 그룹의 길이는 주석으로 표시됩니다. 와이어로 인코딩될 때 가장 중요한 비트는 가장 왼쪽에 있습니다. ABNF에서\). 다음 그림에는 프레이밍에 대한 높은 수준의 개요가 나와 있습니다. 아래 그림과 이 섹션의 뒷부분에 지정된 ABNF가 충돌하는 경우 그림이 권위가 있습니다.
```text
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
FIN: 1 bit
```
- 메시지의 마지막 조각임을 나타냅니다. 첫 번째 조각은 마지막 조각일 수도 있습니다.\(MAY\)
```text
RSV1, RSV2, RSV3: 1 bit each
```
- 0이 아닌 값에 대한 의미를 정의하는 확장이 협상되지 않는 한 0이어야 합니다. 0이 아닌 값이 수신되고 협상된 확장 중 어느 것도 0이 아닌 값의 의미를 정의하지 않으면 수신 엔드포인트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST, MUST\)
```text
Opcode: 4 bits
```
- "페이로드 데이터"의 해석을 정의합니다. 알 수 없는 opcode가 수신되면 수신 엔드포인트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다. 다음 값이 정의됩니다.\(MUST\)
- \* %x0은 연속 프레임을 나타냅니다.
- \* %x1은 텍스트 프레임을 나타냅니다.
- \* %x2는 바이너리 프레임을 나타냅니다.
- \* %x3-7은 추가 비제어 프레임을 위해 예약되어 있습니다.
- \* %x8은 연결 종료를 나타냅니다.
- \* %x9는 핑을 나타냅니다.
- \* %xA는 탁구를 나타냅니다.
- \* %xB-F는 추가 제어 프레임을 위해 예약되어 있습니다.
```text
Mask: 1 bit
```
- "페이로드 데이터"가 마스킹되는지 여부를 정의합니다. 1로 설정되면 마스킹 키가 마스킹 키에 존재하며 이는 섹션 5.3에 따라 "페이로드 데이터"를 마스크 해제하는 데 사용됩니다. 클라이언트에서 서버로 전송되는 모든 프레임에는 이 비트가 1로 설정되어 있습니다.
페이로드 길이: 7비트, 7+16비트 또는 7+64비트
- "페이로드 데이터"의 길이\(바이트\): 0-125이면 페이로드 길이입니다. 126인 경우 16비트 부호 없는 정수로 해석되는 다음 2바이트가 페이로드 길이입니다. 127인 경우 64비트 부호 없는 정수\(가장 중요한 비트는 0이어야 함\)로 해석되는 다음 8바이트가 페이로드 길이입니다. 멀티바이트 길이 수량은 네트워크 바이트 순서로 표현됩니다. 모든 경우에 최소 바이트 수를 사용하여 길이를 인코딩해야 합니다. 예를 들어 124바이트 길이의 문자열 길이는 시퀀스 126, 0, 124로 인코딩할 수 없습니다. 페이로드 길이는 다음과 같습니다. "확장 데이터"의 길이 + "응용 프로그램 데이터"의 길이. "확장 데이터"의 길이는 0일 수 있으며, 이 경우 페이로드 길이는 "애플리케이션 데이터"의 길이입니다.\(MUST, MUST\)
마스킹 키: 0 또는 4바이트
- 클라이언트에서 서버로 전송되는 모든 프레임은 프레임 내에 포함된 32비트 값으로 마스크됩니다. 이 필드는 마스크 비트가 1로 설정되면 존재하고 마스크 비트가 0으로 설정되면 존재하지 않습니다. 클라이언트-서버 마스킹에 대한 자세한 내용은 섹션 5.3을 참조하십시오.
```text
Payload data: (x+y) bytes
```
- "페이로드 데이터"는 "애플리케이션 데이터"가 연결된 "확장 데이터"로 정의됩니다.
```text
Extension data: x bytes
```
- 확장이 협상되지 않은 경우 "확장 데이터"는 0바이트입니다. 모든 확장은 "확장 데이터"의 길이, 또는 해당 길이를 계산하는 방법, 핸드셰이크 시작 중에 확장 사용을 협상하는 방법을 지정해야 합니다. "확장 데이터"가 있는 경우 총 페이로드 길이에 포함됩니다.\(MUST\)
```text
Application data: y bytes
```
- 임의의 "응용 프로그램 데이터"는 "확장 데이터" 다음 프레임의 나머지 부분을 차지합니다. "애플리케이션 데이터"의 길이는 페이로드 길이에서 "확장 데이터"의 길이를 뺀 것과 같습니다.
기본 프레이밍 프로토콜은 다음 ABNF \[RFC5234\]에 의해 공식적으로 정의됩니다. 이 데이터의 표현은 ASCII 문자가 아닌 이진수라는 점에 유의하는 것이 중요합니다. 따라서 %x0 / %x1 값을 갖는 1비트 길이의 필드는 문자 "0" 또는 "1을 나타내는 전체 바이트\(옥텟\)가 아니라 값이 0 또는 1인 단일 비트로 표시됩니다. "를 ASCII 인코딩으로 사용합니다. %x0-F 사이의 값을 갖는 4비트 길이의 필드는 4비트로 표시되며, 이 값을 갖는 ASCII 문자나 전체 바이트\(옥텟\)로는 다시 표시되지 않습니다. \[RFC5234\]는 문자 인코딩을 지정하지 않습니다. "규칙은 때때로 문자라고 불리는 최종 값의 문자열로 해석됩니다. ABNF에서 문자는 단지 음수가 아닌 정수일 뿐입니다. 특정 컨텍스트에서 값의 특정 매핑\(인코딩\)은 문자 집합\(예: ASCII\)이 지정됩니다." 여기서, 지정된 인코딩은 각 터미널 값이 필드마다 달라지는 지정된 비트 수로 인코딩되는 이진 인코딩입니다.
```text
ws-frame = frame-fin ; 1 bit in length
frame-rsv1 ; 1 bit in length
frame-rsv2 ; 1 bit in length
frame-rsv3 ; 1 bit in length
frame-opcode ; 4 bits in length
frame-masked ; 1 bit in length
frame-payload-length ; either 7, 7+16,
; or 7+64 bits in
; length
[ frame-masking-key ] ; 32 bits in length
frame-payload-data ; n*8 bits in
; length, where
; n >= 0
frame-fin = %x0 ; more frames of this message follow
/ %x1 ; final frame of this message
; 1 bit in length
frame-rsv1 = %x0 / %x1
; 1 bit in length, MUST be 0 unless
; negotiated otherwise
frame-rsv2 = %x0 / %x1
; 1 bit in length, MUST be 0 unless
; negotiated otherwise
frame-rsv3 = %x0 / %x1
; 1 bit in length, MUST be 0 unless
; negotiated otherwise
frame-opcode = frame-opcode-non-control /
frame-opcode-control /
frame-opcode-cont
frame-opcode-cont = %x0 ; frame continuation
frame-opcode-non-control= %x1 ; text frame
/ %x2 ; binary frame
/ %x3-7
; 4 bits in length,
; reserved for further non-control frames
frame-opcode-control = %x8 ; connection close
/ %x9 ; ping
/ %xA ; pong
/ %xB-F ; reserved for further control
; frames
; 4 bits in length
frame-masked = %x0
; frame is not masked, no frame-masking-key
/ %x1
; frame is masked, frame-masking-key present
; 1 bit in length
frame-payload-length = ( %x00-7D )
/ ( %x7E frame-payload-length-16 )
/ ( %x7F frame-payload-length-63 )
; 7, 7+16, or 7+64 bits in length,
; respectively
frame-payload-length-16 = %x0000-FFFF ; 16 bits in length
frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
; 64 bits in length
frame-masking-key = 4( %x00-FF )
; present only if frame-masked is 1
; 32 bits in length
frame-payload-data = (frame-masked-extension-data
frame-masked-application-data)
; when frame-masked is 1
/ (frame-unmasked-extension-data
frame-unmasked-application-data)
; when frame-masked is 0
frame-masked-extension-data = *( %x00-FF )
; reserved for future extensibility
; n*8 bits in length, where n >= 0
frame-masked-application-data = *( %x00-FF )
; n*8 bits in length, where n >= 0
frame-unmasked-extension-data = *( %x00-FF )
; reserved for future extensibility
; n*8 bits in length, where n >= 0
frame-unmasked-application-data = *( %x00-FF )
; n*8 bits in length, where n >= 0
```
---
### **5.3. Client-to-Server Masking**
마스크된 프레임은 섹션 5.2에 정의된 대로 1로 설정된 프레임 마스크 필드를 가져야 합니다.\(MUST\)
마스킹 키는 섹션 5.2에서 프레임 마스킹 키로 정의된 대로 프레임 내에 완전히 포함됩니다. "확장 데이터"와 "애플리케이션 데이터"를 포함하는 프레임 페이로드 데이터와 동일한 섹션에 정의된 "페이로드 데이터"를 마스킹하는 데 사용됩니다.
마스킹 키는 클라이언트가 무작위로 선택한 32비트 값입니다. 마스킹된 프레임을 준비할 때 클라이언트는 허용된 32비트 값 집합에서 새로운 마스킹 키를 선택해야 합니다. 마스킹 키는 예측할 수 없어야 합니다. 따라서 마스킹 키는 강력한 엔트로피 소스에서 파생되어야 하며, 주어진 프레임에 대한 마스킹 키는 서버/프록시가 후속 프레임에 대한 마스킹 키를 예측하는 것을 간단하게 만들어서는 안 됩니다. 마스킹 키의 예측 불가능성은 악성 애플리케이션 작성자가 네트워크에 나타나는 바이트를 선택하는 것을 방지하는 데 필수적입니다. RFC 4086 \[RFC4086\]은 보안에 민감한 애플리케이션에 적합한 엔트로피 소스를 수반하는 것이 무엇인지 논의합니다.\(MUST, MUST NOT\)
마스킹은 "페이로드 데이터"의 길이에 영향을 미치지 않습니다. 마스킹된 데이터를 마스킹되지 않은 데이터로 변환하거나 그 반대로 변환하려면 다음 알고리즘이 적용됩니다. 변환 방향에 관계없이 동일한 알고리즘이 적용됩니다. 예를 들어 데이터를 마스크 해제하는 것과 동일한 단계가 데이터를 마스크하는 데 적용됩니다.
변환된 데이터\("transformed-octet-i"\)의 옥텟 i는 원래 데이터\("original-octet-i"\)의 옥텟 i와 마스킹 키\("masking-key\)의 모듈로 4 인덱스 i에 있는 옥텟의 XOR입니다. -옥텟-j"\):
```text
j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j
```
프레임에서 프레임 페이로드 길이로 표시된 페이로드 길이에는 마스킹 키의 길이가 포함되지 않습니다. 이는 "페이로드 데이터"의 길이입니다\(예: 마스킹 키 다음에 오는 바이트 수\).
---
### **5.4. Fragmentation**
조각화의 주요 목적은 메시지가 시작될 때 해당 메시지를 버퍼링할 필요 없이 크기를 알 수 없는 메시지를 보낼 수 있도록 하는 것입니다. 메시지를 조각화할 수 없는 경우 엔드포인트는 첫 번째 바이트가 전송되기 전에 메시지 길이를 계산할 수 있도록 전체 메시지를 버퍼링해야 합니다. 조각화를 사용하면 서버나 중개자가 적당한 크기의 버퍼를 선택할 수 있으며, 버퍼가 가득 차면 조각을 네트워크에 쓸 수 있습니다.
조각화의 두 번째 사용 사례는 멀티플렉싱을 위한 것입니다. 여기서는 하나의 논리 채널에 있는 큰 메시지가 출력 채널을 독점하는 것이 바람직하지 않으므로 멀티플렉싱이 자유로워야 합니다.
출력 채널을 더 잘 공유하기 위해 메시지를 더 작은 조각으로 분할합니다. \(이 문서에서는 멀티플렉싱 확장에 대해 설명하지 않습니다.\)
확장에 의해 달리 지정되지 않는 한 프레임에는 의미론적 의미가 없습니다. 클라이언트와 서버가 확장을 협상하지 않았거나 일부 확장을 협상한 경우 중개자는 프레임을 병합 및/또는 분할할 수 있습니다. 그러나 중개자는 협상된 모든 확장을 이해하고 프레임을 병합 및/또는 분할하는 방법을 알고 있습니다. 이러한 확장. 이에 대한 한 가지 의미는 확장이 없는 경우 송신자와 수신자가 특정 프레임 경계의 존재에 의존해서는 안 된다는 것입니다.
조각화에는 다음 규칙이 적용됩니다.
o 조각화되지 않은 메시지는 FIN 비트 세트\(섹션 5.2\)와 0이 아닌 opcode가 있는 단일 프레임으로 구성됩니다.
o 조각난 메시지는 FIN 비트가 지워지고 opcode가 0이 아닌 단일 프레임으로 구성되며, 그 뒤에는 FIN 비트가 지워지고 opcode가 0으로 설정된 0개 이상의 프레임이 뒤따르고 FIN 비트가 설정된 단일 프레임으로 종료됩니다. 그리고 opcode는 0입니다. 조각화된 메시지는 개념적으로 페이로드가 조각의 페이로드를 순서대로 연결한 것과 동일한 하나의 더 큰 메시지와 동일합니다. 그러나 확장이 있는 경우 확장이 존재하는 "확장 데이터"의 해석을 정의하므로 이는 사실이 아닐 수도 있습니다. 예를 들어, "확장 데이터"는 첫 번째 조각의 시작 부분에만 존재하고 후속 조각에 적용될 수도 있고, 특정 조각에만 적용되는 각 조각에 "확장 데이터"가 있을 수도 있습니다. "확장 데이터"가 없는 경우 다음 예에서는 조각화가 어떻게 작동하는지 보여줍니다.
- 예: 세 개의 조각으로 전송된 텍스트 메시지의 경우 첫 번째 조각에는 opcode 0x1과 FIN 비트 클리어가 있고, 두 번째 조각에는 opcode 0x0과 FIN 비트 클리어가 있으며, 세 번째 조각에는 opcode가 있습니다. 0x0 및 FIN 비트가 설정됩니다.
o 제어 프레임\(섹션 5.5 참조\)은 조각난 메시지 중간에 삽입될 수 있습니다. 제어 프레임 자체는 조각화되어서는 안 됩니다.\(MAY, MUST NOT\)
o 메시지 조각은 발신자가 보낸 순서대로 수신자에게 전달되어야 합니다.\(MUST\)
o 인터리빙을 해석할 수 있는 확장이 협상되지 않는 한 한 메시지의 조각은 다른 메시지의 조각 사이에 인터리빙되어서는 안 됩니다.\(MUST NOT\)
o 엔드포인트는 조각화된 메시지 도중에 제어 프레임을 처리할 수 있어야 합니다.\(MUST\)
o 발신자는 비통제를 위해 모든 크기의 조각을 생성할 수 있습니다.
- 메시지.\(MAY\)
o 클라이언트와 서버는 조각화된 메시지와 조각화되지 않은 메시지 수신을 모두 지원해야 합니다.\(MUST\)
o 제어 프레임은 조각화될 수 없으므로 중개자는 제어 프레임의 조각화를 변경하려고 시도해서는 안 됩니다.\(MUST NOT\)
o 예약된 비트 값이 사용되고 이러한 값의 의미가 중개자에게 알려지지 않은 경우 중개자는 메시지의 조각화를 변경해서는 안 됩니다.\(MUST NOT\)
o 중개자는 확장이 협상되었으며 중개자가 협상된 확장의 의미를 인식하지 못하는 연결 컨텍스트에서 메시지의 조각화를 변경해서는 안 됩니다. 마찬가지로, WebSocket 연결을 초래한 WebSocket 핸드셰이크를 보지 못한\(및 해당 내용에 대한 알림을 받지 못한\) 중개자는 그러한 연결의 메시지 조각화를 변경해서는 안 됩니다.\(MUST NOT, MUST NOT\)
o 이러한 규칙의 결과로 메시지의 모든 조각은 첫 번째 조각의 opcode에 의해 설정된 것과 동일한 유형입니다. 제어 프레임은 조각화될 수 없으므로 메시지의 모든 조각에 대한 유형은 텍스트, 바이너리 또는 예약된 opcode 중 하나여야 합니다.\(MUST\)
참고: 예를 들어 제어 프레임을 삽입할 수 없는 경우 큰 메시지 뒤에 있으면 핑 대기 시간이 매우 길어집니다. 따라서 조각난 메시지 중간에 제어 프레임을 처리해야 하는 요구 사항이 있습니다.
구현 참고: 확장이 없으면 수신자는 프레임을 처리하기 위해 전체 프레임을 버퍼링할 필요가 없습니다. 예를 들어 스트리밍 API를 사용하는 경우 프레임의 일부가 애플리케이션에 전달될 수 있습니다. 그러나 이 가정은 향후 모든 WebSocket 확장에 적용되지 않을 수도 있습니다.
---
### **5.5. Control Frames**
제어 프레임은 opcode의 최상위 비트가 1인 opcode로 식별됩니다. 현재 제어 프레임에 대해 정의된 opcode에는 0x8\(Close\), 0x9\(Ping\) 및 0xA\(Pong\)가 포함됩니다. Opcode 0xB-0xF는 아직 정의되지 않은 추가 제어 프레임을 위해 예약되어 있습니다.
제어 프레임은 WebSocket에 대한 상태를 전달하는 데 사용됩니다. 조각난 메시지 중간에 제어 프레임을 삽입할 수 있습니다.
모든 제어 프레임의 페이로드 길이는 125바이트 이하여야 하며 조각화되어서는 안 됩니다.\(MUST NOT\)
---
#### **5.5.1. Close**
닫기 프레임에는 0x8의 opcode가 포함되어 있습니다.
닫기 프레임에는 끝점 종료, 너무 큰 프레임을 수신한 끝점 또는 너무 큰 프레임을 수신한 끝점과 같은 닫는 이유를 나타내는 본문\(프레임의 "애플리케이션 데이터" 부분\)이 포함될 수 있습니다. 엔드포인트에서 예상하는 형식을 따르지 않습니다. 본문이 있는 경우 본문의 처음 2바이트는 섹션 7.4에 정의된 /code/ 값이 있는 상태 코드를 나타내는 2바이트 부호 없는 정수\(네트워크 바이트 순서\)여야 합니다. 2바이트 정수 다음에 본문에는 /reason/ 값을 가진 UTF-8로 인코딩된 데이터가 포함될 수 있으며, 이에 대한 해석은 이 사양에서 정의되지 않습니다. 이 데이터는 반드시 사람이 읽을 수 있는 것은 아니지만 연결을 연 스크립트와 관련된 정보를 디버깅하거나 전달하는 데 유용할 수 있습니다. 데이터는 사람이 읽을 수 있다고 보장되지 않으므로 클라이언트는 이를 최종 사용자에게 보여서는 안 됩니다.\(MAY, MUST, MAY, MUST NOT\)
클라이언트에서 서버로 전송된 닫기 프레임은 섹션 5.3에 따라 마스크되어야 합니다.
애플리케이션은 닫기 프레임을 보낸 후 더 이상 데이터 프레임을 보내면 안 됩니다.\(MUST NOT\)
엔드포인트가 닫기 프레임을 수신하고 이전에 닫기 프레임을 보내지 않은 경우 엔드포인트는 응답으로 닫기 프레임을 보내야 합니다. \(응답으로 닫기 프레임을 보낼 때 엔드포인트는 일반적으로 수신한 상태 코드를 에코합니다.\) 가능한 한 빨리 그렇게 해야 합니다. 엔드포인트는 현재 메시지가 전송될 때까지 닫기 프레임 전송을 지연할 수 있습니다\(예를 들어, 조각화된 메시지의 대부분이 이미 전송된 경우 엔드포인트는 닫기 프레임을 보내기 전에 나머지 조각을 보낼 수 있습니다\). 그러나 이미 Close 프레임을 보낸 엔드포인트가 계속해서 데이터를 처리한다는 보장은 없습니다.\(MUST, SHOULD, MAY\)
닫기 메시지를 보내고 받은 후 엔드포인트는 WebSocket 연결이 닫힌 것으로 간주하고 기본 TCP 연결을 닫아야 합니다. 서버는 기본 TCP 연결을 즉시 닫아야 합니다. 클라이언트는 서버가 연결을 닫을 때까지 기다려야 하지만 Close 메시지를 보내고 받은 후 언제든지 연결을 닫을 수 있습니다\(예: 합리적인 시간 내에 서버로부터 TCP Close를 수신하지 못한 경우\).\(MUST, MUST\)
클라이언트와 서버가 모두 동시에 Close 메시지를 보내는 경우 두 끝점 모두 Close 메시지를 보내고 받았으므로 WebSocket 연결이 닫힌 것으로 간주하고 기본 TCP 연결을 닫아야 합니다.
---
#### **5.5.2. Ping**
Ping 프레임에는 0x9의 opcode가 포함되어 있습니다.
핑 프레임에는 "애플리케이션 데이터"가 포함될 수 있습니다.\(MAY\)
Ping 프레임을 수신하면 엔드포인트는 이미 Close 프레임을 수신하지 않은 한 응답으로 Pong 프레임을 보내야 합니다. 가능한 한 빨리 Pong 프레임으로 응답해야 합니다. 퐁 프레임은 섹션 5.5.3에서 논의됩니다.\(MUST, SHOULD\)
엔드포인트는 연결이 설정된 후 연결이 닫히기 전에 언제든지 Ping 프레임을 보낼 수 있습니다.\(MAY\)
참고: Ping 프레임은 연결 유지 또는 원격 끝점이 여전히 응답하는지 확인하는 수단으로 사용될 수 있습니다.
---
#### **5.5.3. Pong**
Pong 프레임에는 0xA의 opcode가 포함되어 있습니다.
섹션 5.5.2에서는 Ping 및 Pong 프레임 모두에 적용되는 요구 사항을 자세히 설명합니다.
Ping 프레임에 대한 응답으로 전송된 Pong 프레임에는 응답 중인 Ping 프레임의 메시지 본문에 있는 것과 동일한 "애플리케이션 데이터"가 있어야 합니다.
엔드포인트가 Ping 프레임을 수신하고 이전 Ping 프레임에 대한 응답으로 아직 Pong 프레임을 전송하지 않은 경우 엔드포인트는 가장 최근에 처리된 Ping 프레임에 대해서만 Pong 프레임을 전송하도록 선택할 수 있습니다.\(MAY\)
Pong 프레임은 요청되지 않은 상태로 전송될 수 있습니다. 이는 단방향 심장 박동 역할을 합니다. 원치 않는 Pong 프레임에 대한 응답은 예상되지 않습니다.\(MAY\)
---
### **5.6. Data Frames**
데이터 프레임\(예: 비제어 프레임\)은 opcode의 최상위 비트가 0인 opcode로 식별됩니다. 현재 데이터 프레임에 대해 정의된 opcode에는 0x1\(텍스트\), 0x2\(Binary\)가 포함됩니다. Opcode 0x3-0x7은 아직 정의되지 않은 추가 비제어 프레임을 위해 예약되어 있습니다.
데이터 프레임은 애플리케이션 계층 및/또는 확장 계층 데이터를 전달합니다. opcode는 데이터의 해석을 결정합니다.
```text
Text
```
- "페이로드 데이터"는 UTF-8로 인코딩된 텍스트 데이터입니다. 특정 텍스트 프레임에는 부분적인 UTF-8 시퀀스가 포함될 수 있습니다. 그러나 전체 메시지에는 유효한 UTF-8이 포함되어야 합니다. 재구성된 메시지의 잘못된 UTF-8은 섹션 8.1에 설명된 대로 처리됩니다.\(MUST\)
```text
Binary
```
- "페이로드 데이터"는 해석이 전적으로 애플리케이션 계층에 달려 있는 임의의 바이너리 데이터입니다.
---
### **5.7. Examples**
o 단일 프레임의 마스크되지 않은 문자 메시지
```text
* 0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")
```
o 단일 프레임으로 마스크된 문자 메시지
```text
* 0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
(contains "Hello")
```
o 조각난 마스크 없는 문자 메시지
```text
* 0x01 0x03 0x48 0x65 0x6c (contains "Hel")
* 0x80 0x02 0x6c 0x6f (contains "lo")
```
o 마스크되지 않은 Ping 요청 및 마스크된 Ping 응답
```text
* 0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello",
but the contents of the body are arbitrary)
* 0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
(contains a body of "Hello", matching the body of the ping)
```
o 마스크되지 않은 단일 프레임의 256바이트 바이너리 메시지
- \* 0x82 0x7E 0x0100 \[바이너리 데이터 256바이트\]
o 마스크되지 않은 단일 프레임의 64KiB 바이너리 메시지
- \* 0x82 0x7F 0x0000000000010000 \[바이너리 데이터 65536바이트\]
---
### **5.8. Extensibility**
프로토콜은 기본 프로토콜에 기능을 추가하는 확장을 허용하도록 설계되었습니다. 연결의 끝점은 핸드셰이크를 여는 동안 모든 확장 사용을 협상해야 합니다. 이 사양은 확장에서 사용할 수 있는 opcode 0x3\~0x7 및 0xB\~0xF, "확장 데이터" 필드, 프레임 헤더의 프레임 rsv1, 프레임 rsv2 및 프레임 rsv3 비트를 제공합니다. 확장 협상은 섹션 9.1에서 더 자세히 논의됩니다. 다음은 확장의 예상되는 용도입니다. 이 목록은 완전하지도 않고 규범적이지도 않습니다.\(MUST\)
o "확장 데이터"는 "애플리케이션 데이터" 이전의 "페이로드 데이터"에 배치될 수 있습니다.
o 프레임당 필요에 따라 예약된 비트를 할당할 수 있습니다.
o 예약된 opcode 값을 정의할 수 있습니다.
o 더 많은 opcode 값이 필요한 경우 예약된 비트를 opcode 필드에 할당할 수 있습니다.
o 더 큰 opcode 또는 더 많은 프레임당 비트를 정의하기 위해 "페이로드 데이터"에서 추가 비트를 할당하는 예약된 비트 또는 "확장" opcode를 정의할 수 있습니다.
---
## **6. Sending and Receiving Data**
---
### **6.1. Sending Data**
WebSocket 연결을 통해 /data/로 구성된 \_WebSocket 메시지를 전송\_하려면 엔드포인트는 다음 단계를 수행해야 합니다.\(MUST\)
1. 엔드포인트는 WebSocket 연결이 OPEN 상태인지 확인해야 합니다\(섹션 4.1 및 4.2.2 참조\). 어느 시점에서든 WebSocket 연결 상태가 변경되면 엔드포인트는 다음 단계를 중단해야 합니다.\(MUST, MUST\)
2. 엔드포인트는 섹션 5.2에 정의된 대로 WebSocket 프레임의 /data/를 캡슐화해야 합니다. 전송할 데이터가 크거나 엔드포인트가 데이터 전송을 시작하려는 시점에 데이터 전체를 사용할 수 없는 경우 엔드포인트는 섹션 5.4에 정의된 대로 일련의 프레임에 데이터를 교대로 캡슐화할 수 있습니다.\(MUST, MAY\)
3. 데이터를 포함하는 첫 번째 프레임의 opcode\(frame-opcode\)는 수신자가 텍스트 또는 이진 데이터로 해석할 데이터에 대해 섹션 5.2의 적절한 값으로 설정되어야 합니다.\(MUST\)
4. 데이터를 포함하는 마지막 프레임의 FIN 비트\(frame-fin\)는 섹션 5.2에 정의된 대로 1로 설정되어야 합니다.\(MUST\)
5. 데이터가 클라이언트에 의해 전송되는 경우 프레임은 섹션 5.3에 정의된 대로 마스크되어야 합니다.\(MUST\)
6. WebSocket 연결을 위해 확장\(9항\)이 협상된 경우 해당 확장의 정의에 따라 추가 고려 사항이 적용될 수 있습니다.
7. 형성된 프레임은 기본 네트워크 연결을 통해 전송되어야 합니다.\(MUST\)
---
### **6.2. Receiving Data**
WebSocket 데이터를 수신하기 위해 엔드포인트는 기본 네트워크 연결을 수신합니다. 수신 데이터는 섹션 5.2에 정의된 대로 WebSocket 프레임으로 구문 분석되어야 합니다. 제어 프레임\(섹션 5.5\)이 수신되면 프레임은 섹션 5.5에 정의된 대로 처리되어야 합니다. 데이터 프레임\(섹션 5.6\)을 수신하면 엔드포인트는 섹션 5.2의 opcode\(frame-opcode\)에 정의된 대로 데이터의 /type/을 기록해야 합니다. 이 프레임의 "애플리케이션 데이터"는 메시지의 /data/로 정의됩니다. 프레임이 조각화되지 않은 메시지\(섹션 5.4\)로 구성되어 있는 경우 유형 /type/ 및 데이터 /data/의 \_A WebSocket 메시지가 수신되었습니다\_라고 합니다. 프레임이 조각화된 메시지의 일부인 경우 후속 데이터 프레임의 "애플리케이션 데이터"가 연결되어 /data/를 형성합니다. FIN 비트\(frame-fin\)에 표시된 대로 마지막 조각이 수신되면 데이터 /data/\(조각의 "애플리케이션 데이터" 연결로 구성됨\)와 함께 \_A WebSocket 메시지가 수신되었습니다\_라고 합니다.\(MUST, MUST, MUST\)
/type/을 입력합니다\(조각화된 메시지의 첫 번째 프레임에 표시됨\). 후속 데이터 프레임은 새로운 WebSocket 메시지에 속하는 것으로 해석되어야 합니다.\(MUST\)
확장\(섹션 9\)은 특히 메시지 경계를 구성하는 것을 포함하여 데이터를 읽는 방법의 의미를 변경할 수 있습니다. 확장 프로그램은 페이로드의 "애플리케이션 데이터" 앞에 "확장 데이터"를 추가하는 것 외에도 "애플리케이션 데이터"를 수정할 수도 있습니다\(압축 등\).\(MAY, MAY\)
서버는 섹션 5.3에 설명된 대로 클라이언트로부터 수신된 데이터 프레임에 대한 마스킹을 제거해야 합니다.\(MUST\)
---
## **7. Closing the Connection**
---
### **7.1. Definitions**
---
#### **7.1.1. Close the WebSocket Connection**
\_WebSocket 연결을 닫기\_ 위해 엔드포인트는 기본 TCP 연결을 닫습니다. 엔드포인트는 TCP 연결과 TLS 세션을 완전히 닫는 방법을 사용해야 하며, 해당되는 경우 수신되었을 수 있는 모든 후행 바이트를 삭제해야 합니다. 엔드포인트는 공격을 받는 경우와 같이 필요할 때 사용 가능한 모든 수단을 통해 연결을 닫을 수 있습니다.\(SHOULD, MAY\)
대부분의 일반적인 경우 기본 TCP 연결은 클라이언트가 아닌 TIME\_WAIT 상태를 유지하도록 서버에 의해 먼저 닫혀야 합니다\(이렇게 하면 최대 2개의 세그먼트 수명\(2MSL\) 동안 연결을 다시 열 수 없게 됩니다. TIME\_WAIT 연결은 더 높은 seq 번호를 가진 새 SYN에서 즉시 다시 열리므로 해당 서버에 영향을 미치지 않습니다. 비정상적인 경우\(예: 합리적인 시간이 지난 후에도 서버로부터 TCP 닫기를 수신하지 못한 경우\) 클라이언트는 TCP 닫기를 시작할 수 있습니다. 따라서 서버가 \_WebSocket 연결을 닫으라는 지시를 받으면 즉시 TCP 닫기를 시작해야 하며, 클라이언트가 동일한 작업을 수행하라는 지시를 받으면 서버에서 TCP 닫기를 기다려야 합니다.\(SHOULD, MAY, SHOULD\)
Berkeley 소켓을 사용하여 C에서 깔끔한 폐쇄를 얻는 방법의 예로, 소켓에서 SHUT\_WR을 사용하여 shutdown\(\)을 호출하고, 피어도 순서대로 종료를 수행했음을 나타내는 반환 값 0을 얻을 때까지 recv\(\)를 호출합니다. 마지막으로 소켓에서 close\(\)를 호출합니다.
---
#### **7.1.2. Start the WebSocket Closing Handshake**
상태 코드\(섹션 7.4\) /code/ 및 선택적인 닫기 이유\(섹션 7.1.6\) /reason/을 사용하여 \_WebSocket Closing Handshake\_를 시작하려면 엔드포인트는 섹션 5.5.1에 설명된 대로 닫기 제어 프레임을 보내야 합니다. 상태 코드는 /code/로 설정되고 종료 이유는 /reason/으로 설정됩니다. 엔드포인트가 닫기 제어 프레임을 전송하고 수신하면 해당 엔드포인트는 섹션 7.1.1에 정의된 대로 \_WebSocket 연결을 닫아야 합니다\_.\(MUST, SHOULD\)
---
#### **7.1.3. The WebSocket Closing Handshake is Started**
Close 제어 프레임을 보내거나 수신하면 \_WebSocket Closing Handshake가 시작\_되었고 WebSocket 연결이 CLOSING 상태에 있다고 말합니다.
---
#### **7.1.4. The WebSocket Connection is Closed**
기본 TCP 연결이 닫히면 \_The WebSocket Connection is Closed\_ 및 WebSocket 연결이 CLOSED 상태에 있다고 말합니다. WebSocket 종료 핸드셰이크가 완료된 후 TCP 연결이 종료된 경우 WebSocket 연결이 \_cleanly\_ 종료되었다고 합니다.
WebSocket 연결을 설정할 수 없는 경우에도 \_The WebSocket Connection is Closed\_라고 표시되지만 \_cleanly\_는 그렇지 않습니다.
---
#### **7.1.5. The WebSocket Connection Close Code**
섹션 5.5.1 및 7.4에 정의된 대로 닫기 제어 프레임에는 종료 이유를 나타내는 상태 코드가 포함될 수 있습니다. WebSocket 연결 닫기는 양쪽 끝점에서 동시에 시작될 수 있습니다. \_WebSocket 연결 닫기 코드\_는 이 프로토콜을 구현하는 애플리케이션이 수신한 첫 번째 닫기 제어 프레임에 포함된 상태 코드\(섹션 7.4\)로 정의됩니다. 이 닫기 제어 프레임에 상태 코드가 포함되어 있지 않으면 \_The WebSocket 연결 닫기 코드\_는 1005로 간주됩니다. \_The WebSocket 연결이 닫혀 있고\_ 끝점에서 닫기 제어 프레임을 수신하지 않은 경우\(예: 기본 전송 연결이 끊어진 경우 발생할 수 있음\) , \_WebSocket 연결 종료 코드\_는 1006으로 간주됩니다.
참고: 두 끝점은 \_WebSocket 연결 종료 코드\_ 값에 동의하지 않을 수 있습니다. 예를 들어, 원격 끝점이 Close 프레임을 보냈지만 로컬 응용 프로그램이 소켓의 수신 버퍼에서 Close 프레임이 포함된 데이터를 아직 읽지 않았고 로컬 응용 프로그램이 독립적으로 연결을 닫고 Close 프레임을 보내기로 결정한 경우 두 끝점은 모두 보내고 받았을 것이다.
프레임을 닫으면 더 이상 닫기 프레임을 보내지 않습니다. 각 끝점은 상대방이 보낸 상태 코드를 \_WebSocket 연결 종료 코드\_로 확인합니다. 따라서 두 엔드포인트가 독립적으로 대략 동시에 \_WebSocket Closing Handshake\_를 시작하는 경우 두 엔드포인트가 \_The WebSocket 연결 닫기 코드\_ 값에 동의하지 않을 수 있습니다.
---
#### **7.1.6. The WebSocket Connection Close Reason**
섹션 5.5.1 및 7.4에 정의된 대로 닫기 제어 프레임에는 종료 이유를 나타내는 상태 코드와 UTF-8로 인코딩된 데이터가 포함될 수 있으며, 해당 데이터의 해석은 끝점에 남아 있으며 이 프로토콜에 의해 정의되지 않습니다. . WebSocket 연결 닫기는 양쪽 끝점에서 동시에 시작될 수 있습니다. \_WebSocket 연결 닫기 이유\_는 이 프로토콜을 구현하는 애플리케이션이 수신한 첫 번째 닫기 제어 프레임에 포함된 상태 코드\(7.4절\) 뒤에 오는 UTF-8 인코딩 데이터로 정의됩니다. 닫기 제어 프레임에 해당 데이터가 없으면 \_WebSocket 연결 닫기 이유\_는 빈 문자열입니다.
참고: 섹션 7.1.5에 명시된 것과 동일한 논리에 따라 두 끝점은 \_WebSocket 연결 종료 이유\_에 동의하지 않을 수 있습니다.
---
#### **7.1.7. Fail the WebSocket Connection**
특정 알고리즘 및 사양에서는 \_WebSocket 연결 실패\_를 위한 엔드포인트가 필요합니다. 그렇게 하려면 클라이언트는 반드시 \_WebSocket 연결을 닫아야 하며\_ 적절한 방식으로 문제를 사용자에게\(특히 개발자에게 유용함\) 보고할 수 있습니다. 마찬가지로, 그렇게 하려면 서버는 반드시 \_WebSocket 연결을 닫고\_ 문제를 기록해야 합니다.\(MUST, MUST\)
엔드포인트가 \_웹소켓 연결 실패\_를 요구하는 시점 이전에 \_웹소켓 연결이 설정\_된 경우, 엔드포인트는 \_웹소켓 연결 닫기\_를 진행하기 전에 적절한 상태 코드\(7.4절\)와 함께 닫기 프레임을 보내야 합니다. 처음에 WebSocket 연결을 실패하게 만든 오류의 특성으로 인해 상대방이 Close 프레임을 수신하고 처리할 수 없을 것 같다고 판단되면 엔드포인트는 Close 프레임 전송을 생략할 수 있습니다. 엔드포인트는 \_WebSocket 연결 실패\_ 지시를 받은 후 원격 엔드포인트에서 데이터\(응답 닫기 프레임 포함\) 처리를 계속 시도해서는 안 됩니다.\(SHOULD, MAY, MUST NOT\)
위에 표시된 경우나 애플리케이션 계층에서 지정한 경우\(예: WebSocket API를 사용하는 스크립트\)를 제외하고 클라이언트는 연결을 닫아서는 안 됩니다.\(SHOULD NOT\)
---
### **7.2. Abnormal Closures**
---
#### **7.2.1. Client-Initiated Closure**
특히 핸드셰이크를 여는 동안 특정 알고리즘에서는 클라이언트가 \_WebSocket 연결 실패\_를 요구합니다. 그렇게 하려면 클라이언트는 섹션 7.1.7에 정의된 대로 \_WebSocket 연결에 실패해야 합니다\_.\(MUST\)
어느 시점에서든 기본 전송 계층 연결이 예기치 않게 끊어지면 클라이언트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
위에 표시된 경우나 애플리케이션 계층에서 지정한 경우\(예: WebSocket API를 사용하는 스크립트\)를 제외하고 클라이언트는 연결을 닫아서는 안 됩니다.\(SHOULD NOT\)
---
#### **7.2.2. Server-Initiated Closure**
특정 알고리즘에서는 핸드셰이크를 여는 동안 서버가 \_WebSocket 연결을 중단\_하도록 요구하거나 권장합니다. 그렇게 하려면 서버는 단순히 \_WebSocket 연결을 닫아야 합니다\_\(섹션 7.1.1\).\(MUST\)
---
#### **7.2.3. Recovering from Abnormal Closure**
다양한 이유로 인해 비정상적인 폐쇄가 발생할 수 있습니다. 이러한 종료는 일시적인 오류로 인해 발생할 수 있으며, 이 경우 다시 연결하면 연결 상태가 좋아지고 정상적인 작업이 재개될 수 있습니다. 이러한 폐쇄는 일시적이지 않은 문제의 결과일 수도 있습니다. 이 경우 배포된 각 클라이언트가 비정상적인 폐쇄를 경험하고 즉시 지속적으로 다시 연결을 시도하면 서버는 다수의 서비스 거부 공격에 해당하는 상황을 경험할 수 있습니다. 클라이언트가 다시 연결을 시도하고 있습니다. 이러한 시나리오의 최종 결과는 서비스가 적시에 복구할 수 없거나 복구가 훨씬 더 어려워지는 것일 수 있습니다.
이를 방지하려면 클라이언트는 이 섹션에 설명된 대로 비정상적인 종료 후 다시 연결을 시도할 때 어떤 형태의 백오프를 사용해야 합니다.\(SHOULD\)
첫 번째 재연결 시도는 임의의 시간만큼 지연되어야 합니다. 이 무작위 지연을 선택하는 매개변수는 클라이언트가 결정합니다. 클라이언트가 구현 경험과 특정 애플리케이션에 따라 지연 길이를 선택하는 다른 간격을 선택할 수 있지만 0\~5초 사이에서 무작위로 선택한 값은 합리적인 초기 지연입니다.\(SHOULD, MAY\)
첫 번째 재연결 시도가 실패하면 후속 재연결 시도는 잘린 이진 지수 백오프와 같은 방법을 사용하여 점점 더 긴 시간만큼 지연되어야 합니다.\(SHOULD\)
---
### **7.3. Normal Closure of Connections**
서버는 원할 때마다 WebSocket 연결을 닫을 수 있습니다. 클라이언트는 WebSocket 연결을 임의로 닫아서는 안 됩니다. 두 경우 모두 엔드포인트는 \_WebSocket Closing Handshake 시작\_\(섹션 7.1.2\) 절차에 따라 폐쇄를 시작합니다.\(MAY, SHOULD NOT\)
---
### **7.4. Status Codes**
설정된 연결을 닫을 때\(예: 열기 핸드셰이크가 완료된 후 닫기 프레임을 보낼 때\) 끝점은 닫힘 이유를 나타낼 수 있습니다. 엔드포인트에 의한 이 이유의 해석과 이 이유에 따라 엔드포인트가 취해야 하는 조치는 이 사양에서 정의되지 않은 상태로 남아 있습니다. 이 사양은 사전 정의된 상태 코드 세트를 정의하고 확장, 프레임워크 및 최종 애플리케이션에서 사용할 수 있는 범위를 지정합니다. 상태 코드 및 관련 텍스트 메시지는 닫기 프레임의 선택적 구성 요소입니다.\(MAY\)
---
#### **7.4.1. Defined Status Codes**
끝점은 닫기 프레임을 보낼 때 다음과 같은 미리 정의된 상태 코드를 사용할 수 있습니다.\(MAY\)
```text
1000
```
- 1000은 정상적인 종료를 나타내며, 연결이 설정된 목적이 달성되었음을 의미합니다.
```text
1001
```
- 1001은 서버가 다운되거나 브라우저가 페이지에서 다른 곳으로 이동하는 등 엔드포인트가 "사라지고 있음"을 나타냅니다.
```text
1002
```
- 1002는 프로토콜 오류로 인해 끝점이 연결을 종료하고 있음을 나타냅니다.
```text
1003
```
- 1003은 엔드포인트가 받아들일 수 없는 유형의 데이터를 수신했기 때문에 연결을 종료하고 있음을 나타냅니다\(예: 텍스트 데이터만 이해하는 엔드포인트가 바이너리 메시지를 받으면 이를 보낼 수 있음\).\(MAY\)
```text
1004
```
- 예약된. 구체적인 의미는 향후 정의될 수 있습니다.
```text
1005
```
- 1005는 예약된 값이며 끝점에 의해 닫기 제어 프레임의 상태 코드로 설정되어서는 안 됩니다. 이는 상태 코드가 실제로 존재하지 않음을 나타내는 상태 코드를 기대하는 애플리케이션에서 사용하도록 지정되었습니다.\(MUST NOT\)
```text
1006
```
- 1006은 예약된 값이며 끝점에 의해 닫기 제어 프레임의 상태 코드로 설정되어서는 안 됩니다. 예를 들어 닫기 제어 프레임을 보내거나 받지 않고 연결이 비정상적으로 닫혔음을 나타내는 상태 코드를 기대하는 응용 프로그램에서 사용하도록 지정되었습니다.\(MUST NOT\)
```text
1007
```
- 1007은 메시지 유형과 일치하지 않는 메시지 내 데이터\(예: 텍스트 메시지 내의 비UTF-8 \[RFC3629\] 데이터\)를 수신했기 때문에 엔드포인트가 연결을 종료하고 있음을 나타냅니다.
```text
1008
```
- 1008은 엔드포인트가 정책을 위반하는 메시지를 수신했기 때문에 연결을 종료하고 있음을 나타냅니다. 이는 더 이상 적합한 상태 코드\(예: 1003 또는 1009\)가 없거나 정책에 대한 특정 세부 정보를 숨길 필요가 있는 경우 반환될 수 있는 일반 상태 코드입니다.
```text
1009
```
- 1009는 처리하기에 너무 큰 메시지를 수신했기 때문에 엔드포인트가 연결을 종료하고 있음을 나타냅니다.
```text
1010
```
- 1010은 서버가 하나 이상의 확장을 협상할 것으로 예상했지만 서버가 WebSocket 핸드셰이크의 응답 메시지에서 이를 반환하지 않았기 때문에 끝점\(클라이언트\)이 연결을 종료하고 있음을 나타냅니다. 확장 기능 목록
- 필요합니다. 닫기 프레임의 /reason/ 부분에 나타나야 합니다. 이 상태 코드는 WebSocket 핸드셰이크가 대신 실패할 수 있으므로 서버에서 사용되지 않습니다.\(SHOULD\)
```text
1011
```
- 1011은 서버가 요청을 이행하지 못하게 하는 예상치 못한 상황이 발생하여 연결을 종료하고 있음을 나타냅니다.
```text
1015
```
- 1015는 예약된 값이며 끝점에 의해 닫기 제어 프레임의 상태 코드로 설정되어서는 안 됩니다. 이는 TLS 핸드셰이크 수행 실패\(예: 서버 인증서를 확인할 수 없음\)로 인해 연결이 닫혔음을 나타내는 상태 코드가 필요한 애플리케이션에서 사용하도록 지정되었습니다.\(MUST NOT\)
---
#### **7.4.2. Reserved Status Code Ranges**
```text
0-999
```
- 0\~999 범위의 상태 코드는 사용되지 않습니다.
```text
1000-2999
```
- 1000-2999 범위의 상태 코드는 이 프로토콜, 향후 개정판 및 영구적이고 쉽게 사용할 수 있는 공개 사양에 지정된 확장에 의한 정의를 위해 예약되어 있습니다.
```text
3000-3999
```
- 3000-3999 범위의 상태 코드는 라이브러리, 프레임워크 및 애플리케이션에서 사용하도록 예약되어 있습니다. 이러한 상태 코드는 IANA에 직접 등록됩니다. 이 코드의 해석은 이 프로토콜에 의해 정의되지 않습니다.
```text
4000-4999
```
- 4000\~4999 범위의 상태 코드는 개인용으로 예약되어 있으므로 등록할 수 없습니다. 이러한 코드는 WebSocket 애플리케이션 간의 사전 합의에 의해 사용될 수 있습니다. 이 코드의 해석은 이 프로토콜에 의해 정의되지 않습니다.
---
## **8. Error Handling**
---
### **8.1. Handling Errors in UTF-8-Encoded Data**
엔드포인트가 바이트 스트림을 UTF-8로 해석하려고 하지만 바이트 스트림이 실제로 유효한 UTF-8 스트림이 아니라는 사실을 발견한 경우 해당 엔드포인트는 반드시 \_WebSocket 연결 실패\_를 해야 합니다. 이 규칙은 핸드셰이크를 여는 동안과 후속 데이터 교환 중에 모두 적용됩니다.\(MUST\)
---
## **9. Extensions**
WebSocket 클라이언트는 이 사양에 대한 확장을 요청할 수 있으며 WebSocket 서버는 클라이언트가 요청한 일부 또는 모든 확장을 수락할 수 있습니다. 서버는 클라이언트가 요청하지 않은 확장으로 응답해서는 안 됩니다. 확장 매개변수가 클라이언트와 서버 간의 협상에 포함된 경우 해당 매개변수는 매개변수가 적용되는 확장의 사양에 따라 선택되어야 합니다.\(MAY, MUST NOT, MUST\)
---
### **9.1. Negotiating Extensions**
클라이언트는 |Sec-WebSocket- Extensions|를 포함하여 확장을 요청합니다. 헤더 필드는 HTTP 헤더 필드\(\[RFC2616\], 섹션 4.2 참조\)에 대한 일반적인 규칙을 따르며 헤더 필드의 값은 다음 ABNF \[RFC2616\]에 의해 정의됩니다. 이 섹션에서는 "묵시적 \*LWS 규칙"을 포함하여 \[RFC2616\]의 ABNF 구문/규칙을 사용하고 있습니다. 협상 중에 아래 ABNF를 준수하지 않는 값이 클라이언트나 서버에 의해 수신되면 이러한 잘못된 데이터의 수신자는 즉시 \_WebSocket 연결 실패\_를 해야 합니다.\(MUST\)
Sec-WebSocket-Extensions = 확장 목록
- 확장 목록 = 1#extension 확장 = 확장 토큰 \*\( ";" 확장 매개변수 \) 확장 토큰 = 등록 토큰 등록 토큰 = 토큰 확장 매개변수 = 토큰 \[ "=" \(토큰 | 인용 문자열\) \] ;따옴표 붙은 문자열 구문 변형을 사용할 때, 인용 문자열 이스케이프 해제 후의 값은 ;'token' ABNF를 준수해야 합니다.\(MUST\)
다른 HTTP 헤더 필드와 마찬가지로 이 헤더 필드는 여러 줄에 걸쳐 분할되거나 결합될 수 있습니다. Ergo, 다음은 동일합니다.\(MAY\)
```text
Sec-WebSocket-Extensions: foo
Sec-WebSocket-Extensions: bar; baz=2
```
정확히 동일합니다
```text
Sec-WebSocket-Extensions: foo, bar; baz=2
```
사용되는 모든 확장 토큰은 등록된 토큰이어야 합니다\(섹션 11.4 참조\). 특정 확장과 함께 제공되는 매개변수는 해당 확장에 대해 정의되어야 합니다. 클라이언트는 광고된 확장 기능만 사용하겠다고 제안할 뿐이며 서버가 해당 확장 기능을 사용하겠다고 표시하지 않는 한 이를 사용해서는 안 됩니다.\(MUST, MUST, MUST NOT\)
확장 순서가 중요하다는 점에 유의하세요. 여러 확장 간의 모든 상호 작용은 확장을 정의하는 문서에서 정의될 수 있습니다. 그러한 정의가 없으면 클라이언트가 요청에 나열한 헤더 필드가 사용하려는 헤더 필드의 기본 설정을 나타내는 것으로 해석되며 나열된 첫 번째 옵션이 가장 바람직합니다. 응답으로 서버에 의해 나열된 확장은 실제로 연결에 사용되는 확장을 나타냅니다. 확장이 데이터 및/또는 프레이밍을 수정하는 경우 데이터에 대한 작업 순서는 확장이 시작 핸드셰이크의 서버 응답에 나열되는 순서와 동일하다고 가정해야 합니다.\(MAY\)
예를 들어, 두 개의 확장 "foo"와 "bar"가 있고 헤더 필드 |Sec-WebSocket-Extensions| 서버에서 전송한 값이 "foo, bar"인 경우 데이터에 대한 작업은 bar\(foo\(data\)\)로 수행됩니다. 즉, 데이터 자체에 대한 변경\(예: 압축\) 또는 " 스택".
허용되는 확장 헤더 필드의 비표준적인 예\(가독성을 위해 긴 줄은 접혀 있습니다\):
```text
Sec-WebSocket-Extensions: deflate-stream
Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
deflate-stream
Sec-WebSocket-Extensions: private-extension
```
서버는 |Sec-WebSocket-Extensions|를 포함하여 하나 이상의 확장을 허용합니다. 클라이언트가 요청한 하나 이상의 확장이 포함된 헤더 필드입니다. 해석
모든 확장 매개변수와 클라이언트가 요청한 매개변수 세트에 대한 서버의 유효한 응답을 구성하는 것은 각 확장에 의해 정의됩니다.
---
### **9.2. Known Extensions**
확장은 추가 프로토콜 기능을 옵트인하는 구현을 위한 메커니즘을 제공합니다. 이 문서에서는 확장을 정의하지 않지만 구현에서는 별도로 정의된 확장을 사용할 수 있습니다.\(MAY\)
---
## **10. Security Considerations**
이 섹션에서는 WebSocket 프로토콜에 적용할 수 있는 몇 가지 보안 고려 사항을 설명합니다. 특정 보안 고려 사항은 이 섹션의 하위 섹션에 설명되어 있습니다.
---
### **10.1. Non-Browser Clients**
WebSocket 프로토콜은 예를 들어 |Origin|을 확인하여 웹 브라우저와 같은 신뢰할 수 있는 애플리케이션 내에서 실행되는 악성 JavaScript로부터 보호합니다. 헤더 필드\(아래 참조\). 자세한 내용은 섹션 1.6을 참조하세요. 이러한 가정은 능력이 더 뛰어난 클라이언트의 경우에는 적용되지 않습니다.
이 프로토콜은 웹 페이지의 스크립트에서 사용하도록 고안되었지만 호스트에서 직접 사용할 수도 있습니다. 이러한 호스트는 자신을 대신하여 행동하므로 가짜 |Origin|을 보낼 수 있습니다. 헤더 필드는 서버를 오해하게 만듭니다. 따라서 서버는 알려진 원본의 스크립트와 직접 통신하고 있다고 가정하는 데 주의해야 하며 예상치 못한 방식으로 액세스할 수 있다는 점을 고려해야 합니다. 특히, 서버는 어떤 입력도 유효하다고 신뢰해서는 안 됩니다.
예: 서버가 SQL 쿼리의 일부로 입력을 사용하는 경우 서버가 SQL 주입에 취약하지 않도록 SQL 서버로 전달되기 전에 모든 입력 텍스트를 이스케이프해야 합니다.
---
### **10.2. Origin Considerations**
웹페이지의 입력을 처리하지 않고 특정 사이트에 대해서만 처리하도록 의도된 서버는 |원본|을 확인해야 합니다. 필드는 그들이 기대하는 원점입니다. 표시된 원본이 서버에서 허용되지 않는 경우 HTTP 403 Forbidden 상태 코드가 포함된 응답으로 WebSocket 핸드셰이크에 응답해야 합니다\(SHOULD\).\(SHOULD, SHOULD\)
```text
The |Origin| header field protects from the attack cases when the
untrusted party is typically the author of a JavaScript application
that is executing in the context of the trusted client. The client
itself can contact the server and, via the mechanism of the |Origin|
```
헤더 필드에서 해당 통신 권한을 JavaScript 애플리케이션으로 확장할지 여부를 결정합니다. 이는 브라우저가 아닌 사용자가 연결을 설정하는 것을 방지하는 것이 아니라 잠재적으로 악의적인 JavaScript의 제어를 받는 신뢰할 수 있는 브라우저가 WebSocket 핸드셰이크를 위조할 수 없도록 하는 것입니다.
---
### **10.3. Attacks On Infrastructure (Masking)**
WebSocket을 통한 공격의 대상이 되는 엔드포인트 외에도 프록시와 같은 웹 인프라의 다른 부분도 공격의 대상이 될 수 있습니다.
이 프로토콜이 개발되면서, 야생에 배포된 캐싱 프록시의 중독을 초래하는 프록시에 대한 공격 클래스를 입증하기 위한 실험이 수행되었습니다\[TALKING\]. 공격의 일반적인 형태는 "공격자"의 제어 하에 있는 서버에 대한 연결을 설정하고, WebSocket 프로토콜이 연결을 설정하기 위해 수행하는 것과 유사한 HTTP 연결에서 업그레이드를 수행한 다음, 업그레이드된 연결을 통해 데이터를 전송하는 것입니다. 알려진 특정 리소스에 대한 GET 요청과 같습니다\(공격에서는 적중이나 광고 제공 네트워크의 리소스를 추적하기 위해 널리 배포된 스크립트와 같을 수 있음\). 원격 서버는 가짜 GET 요청에 대한 응답처럼 보이는 것으로 응답하고 이 응답은 배포된 중개자 중 0이 아닌 비율에 의해 캐시되어 캐시를 손상시킵니다. 이 공격의 최종 효과는 사용자가 공격자가 제어하는 웹 사이트를 방문하도록 확신할 수 있는 경우 공격자는 잠재적으로 해당 사용자와 동일한 캐시 뒤에 있는 다른 사용자의 캐시를 감염시키고 다른 원본에서 악성 스크립트를 실행하여 시스템을 손상시킬 수 있다는 것입니다. 웹 보안 모델.
배포된 중개자에 대한 이러한 공격을 방지하려면 응용 프로그램에서 제공하는 데이터에 HTTP를 준수하지 않는 프레이밍을 붙이는 것만으로는 충분하지 않습니다. 각 부적합 중개자가 이러한 비HTTP 프레이밍을 건너뛰지 않는다는 것을 철저하게 발견하고 테스트하는 것은 불가능하기 때문입니다. 프레임 페이로드에서 잘못 작동합니다. 따라서 채택된 방어 방법은 클라이언트에서 서버로의 모든 데이터를 마스킹하여 원격 스크립트\(공격자\)가 전송되는 데이터가 유선에 나타나는 방식을 제어할 수 없으므로 잘못 해석될 수 있는 메시지를 구성할 수 없도록 하는 것입니다. HTTP 요청으로서의 중개자.
클라이언트는 데이터를 제공하는 최종 애플리케이션에서 예측할 수 없는 알고리즘을 사용하여 각 프레임에 대해 새로운 마스킹 키를 선택해야 합니다. 예를 들어, 각 마스킹은 암호화된 강력한 난수 생성기에서 추출될 수 있습니다. 동일한 키가 사용되거나 다음 키가 선택되는 방식에 대해 해독 가능한 패턴이 존재하는 경우 공격자는 마스킹된 경우 다음 키가 선택된 것처럼 보일 수 있는 메시지를 보낼 수 있습니다.\(MUST\)
HTTP 요청\(공격자가 회선에서 보려는 메시지를 가져와 사용할 다음 마스킹 키로 마스킹함으로써 클라이언트가 이를 적용할 때 마스킹 키가 효과적으로 데이터의 마스크를 해제합니다\).
또한 클라이언트에서 프레임 전송이 시작된 후에는 해당 프레임의 페이로드\(애플리케이션 제공 데이터\)가 애플리케이션에 의해 수정될 수 없어야 합니다. 그렇지 않으면 공격자는 초기 데이터가 알려진 값\(예: 모두 0\)인 긴 프레임을 보내고 데이터의 첫 번째 부분을 수신하면 사용되는 마스킹 키를 계산한 다음 아직 확인되지 않은 데이터를 수정할 수 있습니다. 마스크되면 HTTP 요청으로 표시되도록 프레임에 전송됩니다. \(이것은 본질적으로 알려지거나 예측 가능한 마스킹 키를 사용하는 이전 단락에서 설명한 것과 동일한 문제입니다.\) 추가 데이터가 전송되거나 전송될 데이터가 어떻게든 변경되면 해당 새 데이터 또는 변경된 데이터를 새 프레임에서 전송해야 합니다. 따라서 새로운 마스킹 키를 사용합니다. 즉, 프레임 전송이 시작되면 원격 스크립트\(애플리케이션\)에서 내용을 수정할 수 없어야 합니다.
보호되는 위협 모델은 클라이언트가 HTTP 요청으로 보이는 데이터를 보내는 모델입니다. 따라서 마스킹해야 할 채널은 클라이언트에서 서버로 전달되는 데이터입니다. 서버에서 클라이언트로 전달되는 데이터는 응답처럼 보이도록 만들 수 있지만 이 요청을 수행하려면 클라이언트도 요청을 위조할 수 있어야 합니다. 따라서 양방향으로 데이터를 마스킹할 필요는 없다고 간주되었습니다\(서버에서 클라이언트로의 데이터는 마스킹되지 않음\).
마스킹을 통해 제공되는 보호에도 불구하고 비호환 HTTP 프록시는 마스킹을 적용하지 않는 클라이언트 및 서버의 이러한 유형의 중독 공격에 여전히 취약합니다.
---
### **10.4. Implementation-Specific Limits**
여러 프레임에서 리어셈블리한 후 프레임 크기 또는 총 메시지 크기와 관련하여 구현 및/또는 플랫폼별 제한 사항이 있는 구현은 이러한 제한을 초과하지 않도록 스스로를 보호해야 합니다\(MUST\). \(예를 들어, 악의적인 엔드포인트는 단일 큰 프레임\(예: 크기 2\*\*60\)을 보내거나 작은 프레임의 긴 스트림을 보내 피어의 메모리를 소진시키거나 서비스 거부 공격을 시도할 수 있습니다. 조각화된 메시지의 일부입니다.\) 이러한 구현은 프레임 크기와 여러 프레임에서 리어셈블리한 후의 전체 메시지 크기에 제한을 적용해야 합니다\(SHOULD\).\(MUST, SHOULD\)
---
### **10.5. WebSocket Client Authentication**
이 프로토콜은 WebSocket 핸드셰이크 중에 서버가 클라이언트를 인증할 수 있는 특정 방법을 규정하지 않습니다. WebSocket 서버는 쿠키, HTTP 인증, TLS 인증 등 일반 HTTP 서버에서 사용할 수 있는 모든 클라이언트 인증 메커니즘을 사용할 수 있습니다.
---
### **10.6. Connection Confidentiality and Integrity**
연결 기밀성과 무결성은 TLS\(wss URI\)를 통해 WebSocket 프로토콜을 실행하여 제공됩니다. WebSocket 구현은 TLS를 지원해야 하며 동료와 통신할 때 이를 사용해야 합니다.\(MUST\)
TLS를 사용하는 연결의 경우 TLS가 제공하는 이점은 TLS 핸드셰이크 중에 협상된 알고리즘의 강도에 따라 크게 달라집니다. 예를 들어 일부 TLS 암호화 메커니즘은 연결 기밀성을 제공하지 않습니다. 합리적인 수준의 보호를 달성하려면 클라이언트는 Strong TLS 알고리즘만 사용해야 합니다. "웹 보안 컨텍스트: 사용자 인터페이스 지침" \[W3C.REC-wsc-ui-20100812\]에서는 강력한 TLS 알고리즘을 구성하는 요소에 대해 설명합니다. \[RFC5246\]은 부록 A.5 및 부록 D.3에 추가 지침을 제공합니다.
---
### **10.7. Handling of Invalid Data**
들어오는 데이터는 항상 클라이언트와 서버 모두에서 검증되어야 합니다. 언제든지 엔드포인트가 이해하지 못하는 데이터에 직면하거나 엔드포인트가 입력의 안전성을 결정하는 일부 기준을 위반하는 데이터에 직면하거나 엔드포인트가 예상한 값과 일치하지 않는 오프닝 핸드셰이크를 발견하는 경우\( 예를 들어, 클라이언트 요청의 경로나 출처가 잘못된 경우\) 엔드포인트는 TCP 연결을 끊을 수 있습니다. 성공적인 WebSocket 핸드셰이크 후에 잘못된 데이터가 수신된 경우 엔드포인트는 \_WebSocket 연결 닫기\_를 진행하기 전에 적절한 상태 코드\(섹션 7.4\)와 함께 닫기 프레임을 보내야 합니다. 적절한 상태 코드와 함께 닫기 프레임을 사용하면 문제를 진단하는 데 도움이 될 수 있습니다. WebSocket 핸드셰이크 중에 잘못된 데이터가 전송되면 서버는 적절한 HTTP \[RFC2616\] 상태 코드를 반환해야 합니다.\(MUST, MAY, SHOULD, SHOULD\)
잘못된 인코딩을 사용하여 텍스트 데이터를 보낼 때 일반적인 보안 문제가 발생합니다. 이 프로토콜은 바이너리 또는 기타 유형이 아닌 텍스트 데이터 유형의 메시지에 UTF-8로 인코딩된 데이터가 포함되도록 지정합니다. 길이가 여전히 표시되어 있지만 이 프로토콜을 구현하는 응용 프로그램은 길이를 사용하여 프레임이 실제로 끝나는 위치를 결정해야 합니다.
인코딩은 이 프로토콜을 기반으로 구축된 애플리케이션이 만들 수 있는 가정을 깨뜨릴 수 있으며, 이는 데이터의 잘못된 해석부터 데이터 손실 또는 잠재적인 보안 버그까지 이어질 수 있습니다.
---
### **10.8. Use of SHA-1 by the WebSocket Handshake**
이 문서에 설명된 WebSocket 핸드셰이크는 충돌 저항이나 두 번째 사전 이미지 공격에 대한 저항\(\[RFC4270\]에 설명됨\)과 같은 SHA-1의 보안 속성에 의존하지 않습니다.
---
## **11. IANA Considerations**
---
### **11.1. Registration of New URI Schemes**
---
#### **11.1.1. Registration of "ws" Scheme**
어 |ws| URI는 WebSocket 서버 및 리소스 이름을 식별합니다.
```text
URI scheme name
ws
Status
Permanent
```
URI 체계 구문
- ABNF \[RFC5234\] 구문과 URI 사양 \[RFC3986\]의 ABNF 터미널 사용:
```text
"ws:" "//" authority path-abempty [ "?" query ]
```
<path-abempty\> 및 <query\> \[RFC3986\] 구성 요소는 원하는 서비스 종류를 식별하기 위해 서버로 전송되는 리소스 이름을 구성합니다. 다른 구성 요소는 \[RFC3986\]에 설명된 의미를 갖습니다.
URI 체계 의미론
- 이 체계의 유일한 작업은 WebSocket 프로토콜을 사용하여 연결을 여는 것입니다.
인코딩 고려 사항
- 위에 정의된 구문에 의해 제외된 호스트 구성 요소의 문자는 \[RFC3987\]에 지정된 대로 유니코드에서 ASCII로 변환되거나 대체되어야 합니다. 체계 기반 정규화를 위해 호스트 구성 요소의 국제화된 도메인 이름\(IDN\) 형식과 퓨니코드로의 변환은 동일한 것으로 간주됩니다\(\[RFC3987\]의 섹션 5.3.3 참조\).\(MUST\)
- 위에 정의된 구문에 의해 제외된 다른 구성 요소의 문자는 먼저 문자를 UTF-8로 인코딩한 다음 URI \[RFC3986\]에 정의된 대로 백분율 인코딩 형식을 사용하여 해당 바이트를 대체하여 유니코드에서 ASCII로 변환되어야 합니다. 국제화된 자원 식별자\(IRI\) \[RFC3987\] 사양.\(MUST\)
이 URI 체계 이름을 사용하는 애플리케이션/프로토콜
- 웹소켓 프로토콜
상호 운용성 고려 사항
- WebSocket을 사용하려면 HTTP 버전 1.1 이상이 필요합니다.
```text
Security considerations
See "Security Considerations" section.
Contact
HYBI WG <hybi@ietf.org>
Author/Change controller
IETF <iesg@ietf.org>
References
RFC 6455
```
---
#### **11.1.2. Registration of "wss" Scheme**
|wss| URI는 WebSocket 서버와 리소스 이름을 식별하고 해당 연결을 통한 트래픽이 TLS\(데이터 기밀성, 무결성, 엔드포인트 인증과 같은 TLS의 표준 이점 포함\)를 통해 보호됨을 나타냅니다.
```text
URI scheme name
wss
Status
Permanent
```
URI 체계 구문
- ABNF \[RFC5234\] 구문과 URI 사양 \[RFC3986\]의 ABNF 터미널 사용:
```text
"wss:" "//" authority path-abempty [ "?" query ]
```
<path-abempty\> 및 <query\> 구성 요소는 원하는 서비스 종류를 식별하기 위해 서버로 전송되는 리소스 이름을 형성합니다. 다른 구성 요소는 \[RFC3986\]에 설명된 의미를 갖습니다.
URI 체계 의미론
- 이 체계의 유일한 작업은 TLS를 사용하여 암호화된 WebSocket 프로토콜을 사용하여 연결을 여는 것입니다.
인코딩 고려 사항
- 위에 정의된 구문에 의해 제외된 호스트 구성 요소의 문자는 \[RFC3987\]에 지정된 대로 유니코드에서 ASCII로 변환되거나 대체되어야 합니다. 체계 기반 정규화를 위해 호스트 구성 요소의 IDN 형식과 퓨니코드로의 변환은 동일한 것으로 간주됩니다\(\[RFC3987\]의 섹션 5.3.3 참조\).\(MUST\)
- 위에 정의된 구문에 의해 제외된 다른 구성 요소의 문자는 먼저 문자를 UTF-8로 인코딩한 다음 URI \[RFC3986\]에 정의된 대로 백분율 인코딩 형식을 사용하여 해당 바이트를 대체하여 유니코드에서 ASCII로 변환되어야 합니다. IRI \[RFC3987\] 사양.\(MUST\)
이 URI 체계 이름을 사용하는 애플리케이션/프로토콜
- TLS를 통한 WebSocket 프로토콜
상호 운용성 고려 사항
- WebSocket을 사용하려면 HTTP 버전 1.1 이상이 필요합니다.
```text
Security considerations
See "Security Considerations" section.
Contact
HYBI WG <hybi@ietf.org>
Author/Change controller
IETF <iesg@ietf.org>
References
RFC 6455
```
---
### **11.2. Registration of the "WebSocket" HTTP Upgrade Keyword**
이 섹션에서는 RFC 2817 \[RFC2817\]에 따라 HTTP 업그레이드 토큰 레지스트리에 등록된 키워드를 정의합니다.
토큰 이름
- 웹소켓
```text
Author/Change controller
IETF <iesg@ietf.org>
Contact
HYBI <hybi@ietf.org>
References
RFC 6455
```
---
### **11.3. Registration of New HTTP Header Fields**
---
#### **11.3.1. Sec-WebSocket-Key**
이 섹션에서는 영구 메시지 헤더 필드 이름 레지스트리 \[RFC3864\]에 등록된 헤더 필드에 대해 설명합니다.
```text
Header field name
Sec-WebSocket-Key
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
RFC 6455
```
관련 정보
- 이 헤더 필드는 WebSocket 열기 핸드셰이크에만 사용됩니다.
|Sec-WebSocket-Key| 헤더 필드는 WebSocket 열기 핸드셰이크에 사용됩니다. 유효한 WebSocket 열기 핸드셰이크를 수신했음을 증명하기 위해 서버에서 사용하는 정보의 일부를 제공하기 위해 클라이언트에서 서버로 전송됩니다. 이는 서버가 의심하지 않는 WebSocket 서버에 데이터를 보내는 데 악용되는 비 WebSocket 클라이언트\(예: HTTP 클라이언트\)의 연결을 허용하지 않도록 하는 데 도움이 됩니다.
|Sec-WebSocket-Key| 헤더 필드는 HTTP 요청에 두 번 이상 나타나서는 안 됩니다.\(MUST NOT\)
---
#### **11.3.2. Sec-WebSocket-Extensions**
이 섹션에서는 영구 메시지 헤더 필드 이름 레지스트리 \[RFC3864\]에 등록하기 위한 헤더 필드에 대해 설명합니다.
```text
Header field name
Sec-WebSocket-Extensions
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
RFC 6455
```
관련 정보
- 이 헤더 필드는 WebSocket 열기 핸드셰이크에만 사용됩니다.
|Sec-WebSocket-Extensions| 헤더 필드는 WebSocket 열기 핸드셰이크에 사용됩니다. 처음에는 클라이언트에서 서버로 전송된 다음 연결 기간 동안 사용할 프로토콜 수준 확장 집합에 동의하기 위해 서버에서 클라이언트로 전송됩니다.
|Sec-WebSocket-Extensions| 헤더 필드는 HTTP 요청에서 여러 번 나타날 수 있습니다\(이는 모든 값을 포함하는 단일 |Sec-WebSocket-Extensions| 헤더 필드와 논리적으로 동일합니다. 그러나 |Sec-WebSocket-Extensions| 헤더 필드는 다음보다 많이 나타나서는 안 됩니다. HTTP 응답에서 한 번.\(MAY, MUST NOT\)
---
#### **11.3.3. Sec-WebSocket-Accept**
이 섹션에서는 영구 메시지 헤더 필드 이름 레지스트리 \[RFC3864\]에 등록된 헤더 필드에 대해 설명합니다.
```text
Header field name
Sec-WebSocket-Accept
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
RFC 6455
```
관련 정보
- 이 헤더 필드는 WebSocket 열기 핸드셰이크에만 사용됩니다.
|Sec-WebSocket-Accept| 헤더 필드는 WebSocket 열기 핸드셰이크에 사용됩니다. 서버가 WebSocket 연결을 시작할 것인지 확인하기 위해 서버에서 클라이언트로 전송됩니다.
|Sec-WebSocket-Accept| 헤더는 HTTP 응답에 두 번 이상 나타나서는 안 됩니다.\(MUST NOT\)
---
#### **11.3.4. Sec-WebSocket-Protocol**
이 섹션에서는 영구 메시지 헤더 필드 이름 레지스트리 \[RFC3864\]에 등록된 헤더 필드에 대해 설명합니다.
```text
Header field name
Sec-WebSocket-Protocol
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
RFC 6455
```
관련 정보
- 이 헤더 필드는 WebSocket 열기 핸드셰이크에만 사용됩니다.
|Sec-WebSocket-프로토콜| 헤더 필드는 WebSocket 열기 핸드셰이크에 사용됩니다. 연결의 하위 프로토콜을 확인하기 위해 클라이언트에서 서버로, 다시 서버에서 클라이언트로 전송됩니다. 이를 통해 스크립트는 하위 프로토콜을 선택하고 서버가 해당 하위 프로토콜을 제공하는 데 동의했는지 확인할 수 있습니다.
|Sec-WebSocket-프로토콜| 헤더 필드는 HTTP 요청에 여러 번 나타날 수 있습니다\(이는 모든 값을 포함하는 단일 |Sec-WebSocket-Protocol| 헤더 필드와 논리적으로 동일합니다\). 그러나 |Sec-WebSocket-Protocol| 헤더 필드는 HTTP 응답에 두 번 이상 나타나서는 안 됩니다.\(MAY, MUST NOT\)
---
#### **11.3.5. Sec-WebSocket-Version**
이 섹션에서는 영구 메시지 헤더 필드 이름 레지스트리 \[RFC3864\]에 등록된 헤더 필드에 대해 설명합니다.
```text
Header field name
Sec-WebSocket-Version
Applicable protocol
http
Status
standard
Author/Change controller
IETF
Specification document(s)
RFC 6455
```
관련 정보
- 이 헤더 필드는 WebSocket 열기 핸드셰이크에만 사용됩니다.
|Sec-WebSocket-버전| 헤더 필드는 WebSocket 열기 핸드셰이크에 사용됩니다. 연결의 프로토콜 버전을 나타내기 위해 클라이언트에서 서버로 전송됩니다. 이를 통해 서버는 개시 핸드셰이크와 데이터에서 전송되는 후속 데이터를 올바르게 해석할 수 있으며, 서버가 해당 데이터를 안전한 방식으로 해석할 수 없는 경우 연결을 닫을 수 있습니다. |Sec-WebSocket- 버전| 헤더 필드는 클라이언트로부터 수신된 버전이 서버가 이해하는 버전과 일치하지 않는 경우 WebSocket 핸드셰이크 오류 시 서버에서 클라이언트로 전송됩니다. 이러한 경우 헤더 필드에는 서버에서 지원하는 프로토콜 버전이 포함됩니다.
더 높은 버전 번호가 반드시 더 낮은 버전 번호와 이전 버전과 호환될 것이라는 기대는 없습니다.
|Sec-WebSocket-버전| 헤더 필드는 HTTP 응답에 여러 번 나타날 수 있습니다\(이는 모든 값을 포함하는 단일 |Sec-WebSocket-Version| 헤더 필드와 논리적으로 동일합니다\). 그러나 |Sec-WebSocket-Version| 헤더 필드는 HTTP 요청에 두 번 이상 나타나서는 안 됩니다.\(MAY, MUST NOT\)
---
### **11.4. WebSocket Extension Name Registry**
이 사양은 RFC 5226 \[RFC5226\]에 설정된 원칙에 따라 WebSocket 프로토콜과 함께 사용할 WebSocket 확장 이름에 대한 새로운 IANA 레지스트리를 생성합니다.
이 레지스트리의 일부로 IANA는 다음 정보를 유지 관리합니다.
확장 식별자
- |Sec-WebSocket-Extensions|에서 사용되는 확장의 식별자입니다. 본 사양의 11.3.2항에 등록된 헤더 필드입니다. 값은 이 사양의 섹션 9.1에 정의된 확장 토큰에 대한 요구 사항을 준수해야 합니다.
확장 일반 이름
- 확장명이 일반적으로 참조되는 확장명입니다.
확장 정의
- WebSocket 프로토콜과 함께 사용되는 확장이 정의된 문서에 대한 참조입니다.
알려진 호환되지 않는 확장
- 이 확장이 호환되지 않는 것으로 알려진 확장 식별자 목록입니다.
WebSocket 확장 이름에는 "선착순" IANA 등록 정책 \[RFC5226\]이 적용됩니다.
이 레지스트리에는 초기 값이 없습니다.
---
### **11.5. WebSocket Subprotocol Name Registry**
이 사양은 RFC 5226 \[RFC5226\]에 설정된 원칙에 따라 WebSocket 프로토콜과 함께 사용할 WebSocket 하위 프로토콜 이름에 대한 새로운 IANA 레지스트리를 생성합니다.
이 레지스트리의 일부로 IANA는 다음 정보를 유지 관리합니다.
하위 프로토콜 식별자
- |Sec-WebSocket-Protocol|에서 사용될 하위 프로토콜의 식별자입니다. 본 사양의 11.3.4항에 등록된 헤더 필드입니다. 값은 이 사양 섹션 4.1의 항목 10에 제공된 요구 사항을 준수해야 합니다. 즉, 값은 RFC 2616 \[RFC2616\]에 정의된 토큰이어야 합니다.
하위 프로토콜 일반 이름
- 일반적으로 서브프로토콜을 지칭하는 서브프로토콜의 이름입니다.
하위 프로토콜 정의
- WebSocket 프로토콜과 함께 사용되는 하위 프로토콜이 정의된 문서에 대한 참조입니다.
WebSocket 하위 프로토콜 이름에는 "선착순" IANA 등록 정책 \[RFC5226\]이 적용됩니다.
---
### **11.6. WebSocket Version Number Registry**
이 사양은 RFC 5226 \[RFC5226\]에 설정된 원칙에 따라 WebSocket 프로토콜과 함께 사용되는 WebSocket 버전 번호에 대한 새로운 IANA 레지스트리를 생성합니다.
이 레지스트리의 일부로 IANA는 다음 정보를 유지 관리합니다.
버전 번호
- |Sec-WebSocket-Version|에서 사용할 버전 번호 이 사양의 섹션 4.1에 지정되어 있습니다. 값은 0에서 255\(포함\) 사이의 음수가 아닌 정수여야 합니다.
참조
- 새 버전 번호 또는 버전 번호가 포함된 초안 이름을 요청하는 RFC\(아래 참조\)
상태
- "임시" 또는 "표준". 설명은 아래를 참조하세요.
버전 번호는 "Interim" 또는 "Standard"로 지정됩니다.
"표준" 버전 번호는 RFC에 문서화되어 있으며 이 RFC에서 정의한 버전과 같은 WebSocket 프로토콜의 안정적인 주요 버전을 식별하는 데 사용됩니다. "표준" 버전 번호에는 "IETF 검토" IANA 등록 정책 \[RFC5226\]이 적용됩니다.
"임시" 버전 번호는 Internet-Draft에 문서화되어 구현자가 이 RFC가 게시되기 전에 개발된 버전과 같이 배포된 WebSocket 프로토콜 버전을 식별하고 상호 운용하는 데 사용됩니다. "임시" 버전 번호는 "전문가 검토" IANA 등록 정책 \[RFC5226\]의 적용을 받으며, HYBI 워킹 그룹 의장\(또는 워킹 그룹이 종료된 경우 IETF 애플리케이션 영역의 지역 이사\)이 최초 지정자입니다. 전문가.
IANA는 다음과 같이 레지스트리에 초기값을 추가했습니다.
```text
+--------+-----------------------------------------+----------+
|Version | Reference | Status |
| Number | | |
+--------+-----------------------------------------+----------+
| 0 + draft-ietf-hybi-thewebsocketprotocol-00 | Interim |
+--------+-----------------------------------------+----------+
| 1 + draft-ietf-hybi-thewebsocketprotocol-01 | Interim |
+--------+-----------------------------------------+----------+
| 2 + draft-ietf-hybi-thewebsocketprotocol-02 | Interim |
+--------+-----------------------------------------+----------+
| 3 + draft-ietf-hybi-thewebsocketprotocol-03 | Interim |
+--------+-----------------------------------------+----------+
| 4 + draft-ietf-hybi-thewebsocketprotocol-04 | Interim |
+--------+-----------------------------------------+----------+
| 5 + draft-ietf-hybi-thewebsocketprotocol-05 | Interim |
+--------+-----------------------------------------+----------+
| 6 + draft-ietf-hybi-thewebsocketprotocol-06 | Interim |
+--------+-----------------------------------------+----------+
| 7 + draft-ietf-hybi-thewebsocketprotocol-07 | Interim |
+--------+-----------------------------------------+----------+
| 8 + draft-ietf-hybi-thewebsocketprotocol-08 | Interim |
+--------+-----------------------------------------+----------+
| 9 + Reserved | |
+--------+-----------------------------------------+----------+
| 10 + Reserved | |
+--------+-----------------------------------------+----------+
| 11 + Reserved | |
+--------+-----------------------------------------+----------+
| 12 + Reserved | |
+--------+-----------------------------------------+----------+
| 13 + RFC 6455 | Standard |
+--------+-----------------------------------------+----------+
```
---
### **11.7. WebSocket Close Code Number Registry**
이 사양은 RFC 5226 \[RFC5226\]에 명시된 원칙에 따라 WebSocket 연결 종료 코드 번호에 대한 새로운 IANA 레지스트리를 생성합니다.
이 레지스트리의 일부로 IANA는 다음 정보를 유지 관리합니다.
상태 코드
- 상태 코드는 이 문서의 섹션 7.4에 따라 WebSocket 연결 종료 이유를 나타냅니다. 상태 코드는 1000에서 4999\(포함\) 사이의 정수입니다.
의미
- 상태 코드의 의미. 각 상태 코드는 고유한 의미를 가져야 합니다.
연락하다
- 상태 코드를 보유하는 엔터티의 연락처입니다.
참조
- 상태 코드를 요청하고 그 의미를 정의하는 안정적인 문서입니다. 이는 1000-2999 범위의 상태 코드에 필요하며 3000-3999 범위의 상태 코드에 권장됩니다.
WebSocket 닫기 코드 번호에는 범위에 따라 다른 등록 요구 사항이 적용됩니다. 이 프로토콜 및 후속 버전 또는 확장에서 사용하기 위한 상태 코드 요청에는 "표준 조치", "필요한 사양"\("지정 전문가"를 의미\) 또는 "IESG 검토" IANA 등록 정책 중 하나가 적용되며 다음을 따라야 합니다. 1000\~2999 범위에서 부여됩니다. 라이브러리, 프레임워크 및 애플리케이션에서 사용할 상태 코드 요청에는 "선착순" IANA 등록 정책이 적용되며 3000-3999 범위에서 승인되어야 합니다. 4000-4999의 상태 코드 범위는 개인용으로 지정됩니다. 요청은 WebSocket 프로토콜\(또는 프로토콜의 향후 버전\), 확장 또는 라이브러리/프레임워크/애플리케이션에서 사용할 상태 코드를 요청하는지 여부를 나타내야 합니다.
IANA는 다음과 같이 레지스트리에 초기값을 추가했습니다.
```text
|Status Code | Meaning | Contact | Reference |
-+------------+-----------------+---------------+-----------|
| 1000 | Normal Closure | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1001 | Going Away | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1002 | Protocol error | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1003 | Unsupported Data| hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1004 | ---Reserved---- | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1005 | No Status Rcvd | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1006 | Abnormal Closure| hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1007 | Invalid frame | hybi@ietf.org | RFC 6455 |
| | payload data | | |
-+------------+-----------------+---------------+-----------|
| 1008 | Policy Violation| hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1009 | Message Too Big | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1010 | Mandatory Ext. | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
| 1011 | Internal Server | hybi@ietf.org | RFC 6455 |
| | Error | | |
-+------------+-----------------+---------------+-----------|
| 1015 | TLS handshake | hybi@ietf.org | RFC 6455 |
-+------------+-----------------+---------------+-----------|
```
---
### **11.8. WebSocket Opcode Registry**
이 사양은 RFC 5226 \[RFC5226\]에 명시된 원칙에 따라 WebSocket Opcode에 대한 새로운 IANA 레지스트리를 생성합니다.
이 레지스트리의 일부로 IANA는 다음 정보를 유지 관리합니다.
연산코드
- opcode는 섹션 5.2에 정의된 대로 WebSocket 프레임의 프레임 유형을 나타냅니다. opcode는 0에서 15 사이의 정수입니다.
의미
- opcode 값의 의미.
참조
- opcode를 요청하는 사양입니다.
WebSocket Opcode 번호에는 "표준 조치" IANA 등록 정책 \[RFC5226\]이 적용됩니다.
IANA는 다음과 같이 레지스트리에 초기값을 추가했습니다.
```text
|Opcode | Meaning | Reference |
-+--------+-------------------------------------+-----------|
| 0 | Continuation Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 1 | Text Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 2 | Binary Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 8 | Connection Close Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 9 | Ping Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 10 | Pong Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
```
---
### **11.9. WebSocket Framing Header Bits Registry**
이 사양은 RFC 5226 \[RFC5226\]에 명시된 원칙에 따라 WebSocket 프레이밍 헤더 비트에 대한 새로운 IANA 레지스트리를 생성합니다. 이 레지스트리는 섹션 5.2에서 RSV1, RSV2 및 RSV3으로 표시된 비트의 할당을 제어합니다.
이 비트는 이 사양의 향후 버전 또는 확장을 위해 예약되어 있습니다.
WebSocket 프레이밍 헤더 비트 할당에는 "표준 조치" IANA 등록 정책 \[RFC5226\]이 적용됩니다.
---
## **12. Using the WebSocket Protocol from Other Specifications**
WebSocket 프로토콜은 예를 들어 스크립트 API를 정의하는 사양에서 동적 작성자 정의 콘텐츠에 대한 일반 메커니즘을 제공하기 위해 다른 사양에서 사용되도록 고안되었습니다.
이러한 사양은 먼저 \_WebSocket 연결 설정\_을 수행하여 해당 알고리즘에 다음을 제공해야 합니다.
```text
o The destination, consisting of a /host/ and a /port/.
```
o 하나의 호스트와 포트에서 여러 서비스를 식별할 수 있도록 하는 /resource name/.
o /secure/ 플래그. 연결이 이루어지면 true가 됩니다.
- 암호화되고 그렇지 않으면 거짓입니다.
o 연결을 담당하는 원본 \[RFC6454\]의 ASCII 직렬화입니다.
o 선택적으로 WebSocket 연결을 통해 계층화될 프로토콜을 식별하는 문자열입니다.
/host/, /port/, /resource name/ 및 /secure/ 플래그는 일반적으로 WebSocket URI의 구성 요소를 구문 분석하는 단계를 사용하여 URI에서 가져옵니다. URI가 WebSocket을 지정하지 않으면 이 단계는 실패합니다.
언제든지 연결이 닫혀야 하는 경우 사양은 \_WebSocket 연결 닫기\_ 알고리즘\(섹션 7.1.1\)을 사용해야 합니다.
섹션 7.1.4에서는 \_WebSocket 연결이 닫히는 시점\_을 정의합니다.
연결이 열려 있는 동안 사양은 \_WebSocket 메시지가 수신된 경우\_\(섹션 6.2\) 사례를 처리해야 합니다.
일부 데이터 /data/를 열린 연결로 보내려면 사양에서 \_WebSocket 메시지 보내기\_\(6.1절\)가 필요합니다.
---
## **13. Acknowledgements**
이 프로토콜의 원저자이자 편집자인 Ian Hickson에게 특별한 감사를 드립니다. 이 사양의 초기 설계는 WHATWG 및 WHATWG 메일링 리스트에 참여한 많은 사람들의 도움을 받았습니다. 해당 사양에 대한 기여는 섹션별로 추적되지 않지만 해당 사양에 기여한 모든 사람의 목록은 http://whatwg.org/html5의 WHATWG HTML 사양에 제공됩니다.
본 사양의 "데이터 프레이밍" 섹션에 상당한 양의 텍스트를 제공한 John Tamplin에게도 특별히 감사드립니다.
본 사양의 "데이터 마스킹" 섹션에 대해 상당한 양의 텍스트 및 배경 조사를 제공한 Adam Barth에게도 특별히 감사드립니다.
Apps Area 검토를 담당한 Lisa Dusseault\(그리고 이 작업을 시작하는 데 도움을 준 사람\), Gen-Art 검토를 담당한 Richard Barnes, Transport Area 검토를 담당한 Magnus Westerlund에게 특별히 감사드립니다. 이 작업을 완성하기 위해 뒤에서 끊임없이 노력한 HYBI WG 과거 및 현재 WG 의장인 Joe Hildebrand, Salvatore Loreto 및 Gabriel Montenegro에게 특별한 감사를 드립니다. 마지막으로 담당 지역 책임자인 Peter Saint-Andre에게 특별히 감사드립니다.
HYBI WG 메일링 리스트 토론에 참여하고 아이디어를 제공하거나 자세한 리뷰를 제공한 다음 사람들에게 감사드립니다\(목록은 불완전할 수 있음\): Greg Wilkins, John Tamplin, Willy Tarreau, Maciej Stachowiak, Jamie Lokier, Scott Ferguson, Bjoern Hoehrmann, Julian Reschke, Dave Cridland, Andy Green, Eric Rescorla, Inaki Baz Castillo, Martin Thomson, Roberto Peon, Patrick McManus, Zhong Yu, Bruce Atherton, Takeshi Yoshino, Martin J. Duerst, James Graham, Simon Pieters , Roy T. Fielding, Mykyta Yevstifeyev, Len Holgate, Paul Colomiets, Piotr Kulaga, Brian Raymor, Jan Koehler, Joonas Lehtolahti, Sylvain Hellegouarch, Stephen Farrell, Sean Turner, Pete Resnick, Peter Thorson, Joe Mason, John Fallows 및 Alexander Philippou. 위에 나열된 사람들이 반드시 이 작업의 최종 결과를 지지하는 것은 아닙니다.
---
## **14. References**
---
### **14.1. Normative References**
\[ANSI.X3-4.1986\]
- 미국 국립 표준 협회\(American National Standards Institute\), "코드화된 문자 세트 - 정보 교환을 위한 7비트 미국 표준 코드", ANSI X3.4, 1986.
```text
[FIPS.180-3]
National Institute of Standards and Technology, "Secure
Hash Standard", FIPS PUB 180-3, October 2008,
<http://csrc.nist.gov/publications/fips/fips180-3/
fips180-3_final.pdf>.
```
\[RFC1928\] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D. 및 L. Jones, "SOCKS 프로토콜 버전 5", RFC 1928, 1996년 3월.
\[RFC2119\] Bradner, S., "요구 사항 수준을 나타내기 위해 RFC에서 사용할 핵심 단어", BCP 14, RFC 2119, 1997년 3월.
\[RFC2616\] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
- Masinter, L., Leach, P. 및 T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, 1999년 6월.
\[RFC2817\] Khare, R. 및 S. Lawrence, "HTTP/1.1 내에서 TLS로 업그레이드", RFC 2817, 2000년 5월.
\[RFC2818\] Rescorla, E., "HTTP Over TLS", RFC 2818, 2000년 5월.
\[RFC3629\] Yergeau, F., "UTF-8, ISO 10646의 변환 형식", STD 63, RFC 3629, 2003년 11월.
\[RFC3864\] Klyne, G., Nottingham, M. 및 J. Mogul, "메시지 헤더 필드 등록 절차", BCP 90, RFC 3864, 2004년 9월.
\[RFC3986\] Berners-Lee, T., Fielding, R. 및 L. Masinter, "Uniform Resource Identifier\(URI\): 일반 구문", STD 66, RFC 3986, 2005년 1월.
\[RFC3987\] Duerst, M. 및 M. Suignard, "국제화된 리소스 식별자\(IRI\)", RFC 3987, 2005년 1월.
\[RFC4086\] Eastlake, D., Schiller, J. 및 S. Crocker, "보안을 위한 임의성 요구 사항", BCP 106, RFC 4086, 2005년 6월.
\[RFC4648\] Josefsson, S., "Base16, Base32 및 Base64 데이터 인코딩", RFC 4648, 2006년 10월.
\[RFC5226\] Narten, T. 및 H. Alvestrand, "RFC에서 IANA 고려 사항 섹션 작성 지침", BCP 26, RFC 5226, 2008년 5월.
\[RFC5234\] Crocker, D. 및 P. Overell, "구문 사양을 위한 증강 BNF: ABNF", STD 68, RFC 5234, 2008년 1월.
\[RFC5246\] Dierks, T. 및 E. Rescorla, "TLS\(전송 계층 보안\) 프로토콜 버전 1.2", RFC 5246, 2008년 8월.
```text
[RFC6066] Eastlake, D., "Transport Layer Security (TLS) Extensions:
Extension Definitions", RFC 6066, January 2011.
[RFC6454] Barth, A., "The Web Origin Concept", RFC 6454,
December 2011.
```
---
### **14.2. Informative References**
\[RFC4122\] Leach, P., Mealling, M. 및 R. Salz, "UUID\(Universally Unique IDentifier\) URN 네임스페이스", RFC 4122, 2005년 7월.
\[RFC4270\] Hoffman, P. 및 B. Schneier, "인터넷 프로토콜의 암호화 해시에 대한 공격", RFC 4270, 2005년 11월.
```text
[RFC5321] Klensin, J., "Simple Mail Transfer Protocol", RFC 5321,
October 2008.
```
\[RFC6202\] Loreto, S., Saint-Andre, P., Salsano, S. 및 G. Wilkins, "양방향 HTTP에서 긴 폴링 및 스트리밍 사용에 대한 알려진 문제 및 모범 사례", RFC 6202, 2011년 4월.
```text
[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265,
April 2011.
[TALKING] Huang, L-S., Chen, E., Barth, A., Rescorla, E., and C.
Jackson, "Talking to Yourself for Fun and Profit", 2010,
<http://w2spconf.com/2011/papers/websocket.pdf>.
[W3C.REC-wsc-ui-20100812]
Roessler, T. and A. Saldhana, "Web Security Context: User
Interface Guidelines", World Wide Web Consortium
Recommendation REC-wsc-ui-20100812, August 2010,
<http://www.w3.org/TR/2010/REC-wsc-ui-20100812/>.
Latest version available at
<http://www.w3.org/TR/wsc-ui/>.
[WSAPI] Hickson, I., "The WebSocket API", W3C Working Draft WD-
websockets-20110929, September 2011,
<http://www.w3.org/TR/2011/WD-websockets-20110929/>.
Latest version available at
<http://www.w3.org/TR/websockets/>.
[XMLHttpRequest]
van Kesteren, A., Ed., "XMLHttpRequest", W3C Candidate
Recommendation CR-XMLHttpRequest-20100803, August 2010,
<http://www.w3.org/TR/2010/CR-XMLHttpRequest-20100803/>.
Latest version available at
<http://www.w3.org/TR/XMLHttpRequest/>.
```
---
# **Authors' Addresses**
```text
Ian Fette
Google, Inc.
EMail: ifette+ietf@google.com
URI: http://www.ianfette.com/
Alexey Melnikov
Isode Ltd.
5 Castle Business Village
36 Station Road
Hampton, Middlesex TW12 2BX
UK
EMail: Alexey.Melnikov@isode.com
```
original document link : https://www.ietf.org/rfc/rfc6455.txt
Disclaimer of Accuracy for Translation:
This document is a translation of the original (RFC 6455). While every effort has been made to ensure the accuracy of this translation, it may contain errors or discrepancies. For verification of the content and to ensure consistency with the original document, please refer to the original version.
Non-Commercial Use and Educational Purpose Statement:
This translated document is intended solely for educational purposes and is not to be used for any commercial purposes. The content of this translation is provided to facilitate learning and understanding of the original (RFC 6455) and should not be utilized in any commercial context.
translator : yevgeny hong, used google translator api
contact : hongyevgeny@gmail.com