웹소켓

현행 표준 — 마지막 업데이트

참여하기:
GitHub whatwg/websockets (새 이슈, 열린 이슈)
Matrix에서 채팅
커밋:
GitHub whatwg/websockets/commits
이 커밋 시점의 스냅샷
@whatsockets
테스트:
web-platform-tests websockets/ (진행 중인 작업)
번역 (비규범적):
日本語
简体中文
한국어

개요

이 명세는 웹 애플리케이션이 서버 측 프로세스와 양방향 통신을 유지할 수 있도록 하는 API를 제공합니다.

1. 소개

이 섹션은 비규범적입니다.

웹 애플리케이션이 서버 측 프로세스와 양방향 통신을 유지할 수 있도록 하기 위해, 본 명세는 WebSocket 인터페이스를 소개합니다.

이 인터페이스는 기본 네트워크에 대한 원시 접근을 허용하지 않습니다. 예를 들어, 이 인터페이스를 사용하여 사용자 정의 서버를 통해 메시지를 프록시하지 않고는 IRC 클라이언트를 구현할 수 없습니다.

2. WebSocket 프로토콜 변경

이 섹션은 Fetch에서 정의된 알고리즘과 통합하기 위해 WebSocket 프로토콜 초기 핸드셰이크 클라이언트 요구 사항의 일부를 대체합니다. 이를 통해 CSP, 쿠키, HSTS 및 기타 Fetch-관련 프로토콜이 단일 위치에서 처리됩니다. 이상적으로는 RFC가 이 언어로 업데이트되겠지만, 그것은 결코 쉬운 일이 아닙니다. 아래에서 정의된 WebSocket API는 이 언어를 사용합니다. [WSP] [FETCH]

작동 방식은 WebSocket 프로토콜의 "WebSocket 연결 설정" 알고리즘을 Fetch와 통합된 새로운 알고리즘으로 교체하는 것입니다. "WebSocket 연결 설정"은 연결 설정, 핸드셰이크 요청 생성 및 전송, 핸드셰이크 응답 유효성 검사라는 세 가지 알고리즘으로 구성됩니다. 이는 먼저 핸드셰이크를 생성하고, 연결을 설정하며 핸드셰이크를 전송하고, 마지막으로 응답을 유효성 검사하는 Fetch와는 계층이 다릅니다. 이러한 변경 사항을 읽을 때 이를 염두에 두세요.

2.1. 연결

url을 입력으로 WebSocket 연결을 얻으려면, 다음 단계를 실행합니다:

  1. hosturlhost로 설정합니다.

  2. porturlport로 설정합니다.

  3. resource name을 U+002F (/)로 설정하고, urlpath (비어 있는 문자열 포함)의 문자열을, 있는 경우, U+002F (/)로 서로 구분하여 뒤에 추가합니다.

  4. urlquery가 비어 있지 않으면, U+003F (?), 그리고 urlqueryresource name에 추가합니다.

  5. secureurlscheme이 "http"인 경우 false로, 그렇지 않으면 true로 설정합니다.

  6. WebSocket 프로토콜의 섹션 4.1의 첫 번째 단계 집합의 2단계에서 5단계까지의 요구 사항을 따르며, host, port, resource namesecure를 전달하여 WebSocket 연결을 설정합니다. [WSP]

  7. 해당 연결이 설정되었으면 이를 반환하고, 그렇지 않으면 실패를 반환합니다.

속성이 다르고 공유할 수 없지만, WebSocket 연결은 "일반적인" 연결과 매우 유사합니다.

2.2. 초기 핸드셰이크

url, protocols, client을 입력으로 WebSocket 연결을 설정하려면, 다음 단계를 실행합니다:

  1. requestURLurl의 복사본으로 설정하고, urlscheme이 "ws"인 경우 "http"로, 그렇지 않은 경우 "https"로 설정합니다.

    이 scheme 변경은 fetching과 잘 통합되기 위해 필수적입니다. 예를 들어, HSTS는 이 변경 없이 작동하지 않을 것입니다. WebSocket이 별도의 scheme을 가진 데에는 실제 이유가 없으며, 이는 레거시 유물입니다. [HSTS]

  2. request를 새로운 request로 설정하고, URLrequestURL, clientclient, service-workers mode를 "none", referrer를 "no-referrer", mode를 "websocket", credentials mode를 "include", cache mode를 "no-store" , redirect mode를 "error"로 설정합니다.

  3. `Upgrade`, `websocket`requestheader list에 추가합니다.

  4. `Connection`, `Upgrade`requestheader list에 추가합니다.

  5. keyValue를 forgiving-base64-encoded되고 isomorphic encoded된, 무작위로 선택된 16바이트 값을 포함하는 nonce로 설정합니다.

    무작위로 선택된 값이 바이트 시퀀스 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10이었다면, keyValue는 forgiving-base64-encoded되어 "AQIDBAUGBwgJCgsMDQ4PEC=="로, isomorphic encoded되어 `AQIDBAUGBwgJCgsMDQ4PEC==`로 설정됩니다.

  6. `Sec-WebSocket-Key`, keyValue`requestheader list에 추가합니다.

  7. `Sec-WebSocket-Version`, `13`requestheader list에 추가합니다.

  8. protocols의 각 protocol에 대해, `Sec-WebSocket-Protocol`, protocol`requestheader list에 결합합니다.

  9. permessageDeflate를 사용자 에이전트 정의 "permessage-deflate" 확장 헤더 값으로 설정합니다. [WSP]

    `permessage-deflate; client_max_window_bits`

  10. `Sec-WebSocket-Extensions`, permessageDeflate`requestheader list에 추가합니다.

  11. Fetch requestuseParallelQueue를 true로 설정하고, processResponseresponse로 설정하며 다음 단계를 실행합니다:

    1. response네트워크 오류이거나, 상태가 101이 아니면, WebSocket 연결 실패로 처리합니다.

    2. protocols가 비어 있지 않고, 헤더 리스트 값 추출이 `Sec-WebSocket-Protocol`과 response헤더 리스트를 기준으로 null, 실패, 또는 빈 바이트 시퀀스를 반환하면 WebSocket 연결 실패로 처리합니다.

      이는 The WebSocket Protocol에서 정의된 헤더 체크와 다릅니다. 이는 클라이언트에서 요청하지 않은 하위 프로토콜에 대해서만 다룹니다. 이는 클라이언트에서 요청했지만 서버에서 인정하지 않은 하위 프로토콜을 다룹니다.

    3. The WebSocket Protocol의 섹션 4.1에서 마지막 단계 집합의 2단계에서 6단계까지를 따라 response를 검증합니다. 이는 WebSocket 연결 실패 또는 WebSocket 연결이 설정됨으로 이어집니다.

WebSocket 연결 실패WebSocket 연결이 설정됨은 The WebSocket Protocol에서 정의됩니다. [WSP]

리다이렉트를 따르지 않으며 이 핸드셰이크가 일반적으로 제한되는 이유는 웹 브라우저 컨텍스트에서 심각한 보안 문제가 발생할 수 있기 때문입니다. 예를 들어, 한 경로에 WebSocket 서버가 있고 다른 경로에 열린 HTTP 리다이렉터가 있는 호스트를 고려해 보십시오. 갑작스럽게, 특정 WebSocket URL을 가진 스크립트가 인터넷상의 모든 호스트와 통신하도록 속일 수 있으며(그리고 잠재적으로 비밀을 공유할 수 있습니다), 심지어 해당 URL이 올바른 호스트명을 가지고 있는지 확인하는 경우에도 말입니다.

3. WebSocket 인터페이스

3.1. 인터페이스 정의

WebSocket 클래스에 대한 Web IDL 정의는 다음과 같습니다:

enum BinaryType { "blob", "arraybuffer" };

[Exposed=(Window,Worker)]
interface WebSocket : EventTarget {
  constructor(USVString url, optional (DOMString or sequence<DOMString>) protocols = []);
  readonly attribute USVString url;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSING = 2;
  const unsigned short CLOSED = 3;
  readonly attribute unsigned short readyState;
  readonly attribute unsigned long long bufferedAmount;

  // networking
  attribute EventHandler onopen;
  attribute EventHandler onerror;
  attribute EventHandler onclose;
  readonly attribute DOMString extensions;
  readonly attribute DOMString protocol;
  undefined close(optional [Clamp] unsigned short code, optional USVString reason);

  // messaging
  attribute EventHandler onmessage;
  attribute BinaryType binaryType;
  undefined send((BufferSource or Blob or USVString) data);
};

WebSocket 객체는 url과 연관되며, 이는 URL 레코드입니다.

WebSocket 객체는 binary type과 연관되며, 이는 BinaryType입니다. 초기값은 "blob"이어야 합니다.

WebSocket 객체는 ready state와 연관되며, 이는 연결 상태를 나타내는 숫자입니다. 초기값은 CONNECTING(0)이어야 합니다. 다음 값들을 가질 수 있습니다:

CONNECTING (숫자 값 0)

연결이 아직 설정되지 않았습니다.

OPEN (숫자 값 1)

WebSocket 연결이 설정되었으며 통신이 가능합니다.

CLOSING (숫자 값 2)

연결이 종료 핸드셰이크를 진행 중이거나 close() 메서드가 호출되었습니다.

CLOSED (숫자 값 3)

연결이 종료되었거나 열리지 않았습니다.

socket = new WebSocket(url [, protocols ])

새로운 WebSocket 객체를 생성하며, 즉시 연관된 WebSocket 연결을 설정합니다.

url은 연결이 설정될 URL을 나타내는 문자열입니다. "ws", "wss", "http", "https" 스킴만 허용되며, 다른 스킴은 "SyntaxError" DOMException를 발생시킵니다. 프래그먼트를 포함하는 URL은 항상 이러한 예외를 발생시킵니다.

protocols는 문자열 또는 문자열 배열입니다. 문자열인 경우, 단일 문자열로 구성된 배열과 동일합니다. 생략된 경우 빈 배열과 동일합니다. 배열의 각 문자열은 하위 프로토콜 이름입니다. 서버가 이러한 하위 프로토콜 중 하나를 선택했다고 보고한 경우에만 연결이 설정됩니다. 하위 프로토콜 이름은 The WebSocket Protocol에서 정의한 `Sec-WebSocket-Protocol` 필드 값을 구성하는 요소에 대한 요구 사항을 충족해야 합니다. [WSP]

socket.send(data)

WebSocket 연결을 사용하여 data를 전송합니다. data는 문자열, Blob, ArrayBuffer 또는 ArrayBufferView일 수 있습니다.

socket.close([ code ] [, reason ])

codeWebSocket 연결 종료 코드로, reasonWebSocket 연결 종료 이유로 선택적으로 사용하여 WebSocket 연결을 종료합니다.

socket.url

WebSocket 연결을 설정하는 데 사용된 URL을 반환합니다.

socket.readyState

WebSocket 연결의 상태를 반환합니다. 위에 설명된 값을 가질 수 있습니다.

socket.bufferedAmount

send()를 사용하여 큐에 추가되었지만 아직 네트워크로 전송되지 않은 애플리케이션 데이터(UTF-8 텍스트 및 바이너리 데이터)의 바이트 수를 반환합니다.

WebSocket 연결이 닫힌 경우, 이 속성의 값은 send() 메서드를 호출할 때마다 증가합니다. (연결이 닫힌 후에도 값은 0으로 재설정되지 않습니다.)

socket.extensions

서버에서 선택한 확장을 반환합니다(있는 경우).

socket.protocol

서버에서 선택한 하위 프로토콜을 반환합니다(있는 경우). 이는 생성자의 두 번째 인수의 배열 형식과 함께 하위 프로토콜 협상을 수행하는 데 사용할 수 있습니다.

socket.binaryType

socket의 바이너리 데이터가 스크립트에 노출되는 방식을 나타내는 문자열을 반환합니다:

"blob"

바이너리 데이터가 Blob 형식으로 반환됩니다.

"arraybuffer"

바이너리 데이터가 ArrayBuffer 형식으로 반환됩니다.

기본값은 "blob"입니다.

socket.binaryType = value

바이너리 데이터가 반환되는 방식을 변경합니다.

new WebSocket(url, protocols) 생성자 단계는 다음과 같습니다:
  1. baseURLthis관련 설정 객체API 기본 URL로 설정합니다.

  2. urlRecordURL 파서urlbaseURL로 적용한 결과로 설정합니다.

  3. urlRecord가 실패한 경우, "SyntaxError" DOMException를 발생시킵니다.

  4. urlRecordscheme이 "http"인 경우, urlRecordscheme을 "ws"로 설정합니다.

  5. 그렇지 않고, urlRecordscheme이 "https"인 경우, urlRecordscheme을 "wss"로 설정합니다.

  6. urlRecordscheme이 "ws" 또는 "wss"가 아닌 경우, "SyntaxError" DOMException를 발생시킵니다.

  7. urlRecordfragment가 null이 아닌 경우, "SyntaxError" DOMException를 발생시킵니다.

  8. protocols이 문자열인 경우, protocols를 해당 문자열만 포함하는 시퀀스로 설정합니다.

  9. protocols의 값 중 하나가 중복되거나 The WebSocket Protocol에서 정의한 `Sec-WebSocket-Protocol` 필드 값을 구성하는 요소 요구 사항을 충족하지 못하는 경우, "SyntaxError" DOMException를 발생시킵니다. [WSP]

  10. thisurlurlRecord로 설정합니다.

  11. clientthis관련 설정 객체로 설정합니다.

  12. 이 단계를 병렬로 실행합니다:

    1. urlRecord, protocols, client를 사용하여 WebSocket 연결을 설정합니다. [FETCH]

      WebSocket 연결을 설정하는 알고리즘이 실패하면, 이는 WebSocket 연결 실패 알고리즘을 트리거하며, 이는 WebSocket 연결 닫기 알고리즘을 호출하고, 이는 WebSocket 연결이 닫혔음을 설정하며, close 이벤트를 아래에 설명된 대로 트리거합니다.


url getter의 단계는 thisurl직렬화된 형태로 반환하는 것입니다.

readyState getter의 단계는 thisready state를 반환하는 것입니다.

extensions 속성은 초기에는 빈 문자열을 반환해야 합니다. WebSocket 연결이 설정된 후, 값이 아래에 정의된 대로 변경될 수 있습니다.

protocol 속성은 초기에는 빈 문자열을 반환해야 합니다. WebSocket 연결이 설정된 후, 값이 아래에 정의된 대로 변경될 수 있습니다.

close(code, reason) 메서드의 단계는 다음과 같습니다:
  1. code가 존재하지만 1000과 같거나 3000에서 4999 사이(포함)인 정수가 아닌 경우 "InvalidAccessError" DOMException를 발생시킵니다.

  2. reason이 존재한다면, 다음 하위 단계를 실행합니다:

    1. reasonBytesUTF-8 인코딩reason의 결과로 설정합니다.

    2. reasonBytes가 123 바이트보다 길다면 "SyntaxError" DOMException를 발생시킵니다.

  3. 다음 목록에서 첫 번째로 일치하는 단계를 실행합니다:

    thisready stateCLOSING (2) 또는 CLOSED (3)인 경우

    아무것도 하지 않습니다.

    연결이 이미 종료 중이거나 종료되었습니다. 아직 발생하지 않은 경우, close 이벤트가 결국 아래에 설명된 대로 발생할 것입니다.

    WebSocket 연결이 아직 설정되지 않았으면 [WSP]

    WebSocket 연결 실패를 실행하고 thisready stateCLOSING (2)로 설정합니다. [WSP]

    WebSocket 연결 실패 알고리즘은 WebSocket 연결 닫기 알고리즘을 호출하며, 이는 WebSocket 연결이 닫혔음을 설정하고, close 이벤트를 아래에 설명된 대로 발생시킵니다.

    WebSocket 종료 핸드셰이크가 아직 시작되지 않았으면 [WSP]

    WebSocket 종료 핸드셰이크 시작을 실행하고 thisready stateCLOSING (2)로 설정합니다. [WSP]

    codereason이 모두 없는 경우, WebSocket Close 메시지에는 본문이 없어야 합니다.

    The WebSocket Protocol은 WebSocket 종료 핸드셰이크 시작 알고리즘의 상태 코드가 필수라고 잘못 기술하고 있습니다.

    code가 존재한다면, WebSocket Close 메시지에서 사용할 상태 코드는 code에 의해 제공된 정수여야 합니다. [WSP]

    reason 또한 존재한다면, reasonBytes는 상태 코드 이후 Close 메시지에 제공되어야 합니다. [WSP]

    WebSocket 종료 핸드셰이크 시작 알고리즘은 결국 WebSocket 연결 닫기 알고리즘을 호출하며, 이는 WebSocket 연결이 닫혔음을 설정하고, close 이벤트를 아래에 설명된 대로 발생시킵니다.

    그 외의 경우

    thisready stateCLOSING (2)로 설정합니다.

    WebSocket 종료 핸드셰이크가 시작되며, 이는 결국 WebSocket 연결 닫기 알고리즘을 호출하고, 이는 WebSocket 연결이 닫혔음을 설정하며, 따라서 close 이벤트가 발생합니다. 아래에 설명된 대로.

close() 메서드는 WebSocket 종료 핸드셰이크를 시작하기 전에 이전에 전송된 메시지를 폐기하지 않습니다. 실제로 사용자 에이전트가 여전히 해당 메시지를 전송 중이더라도 핸드셰이크는 메시지 전송이 완료된 후에만 시작됩니다.


bufferedAmount getter의 단계는 send()를 사용하여 큐에 추가되었지만, 이벤트 루프가 마지막으로 1단계에 도달했을 때까지 네트워크에 전송되지 않은 애플리케이션 데이터(UTF-8 텍스트 및 바이너리 데이터)의 바이트 수를 반환하는 것입니다. (따라서 현재 작업 실행 중에 전송된 텍스트도 포함되며, 사용자 에이전트가 스크립트 실행과 병렬로 백그라운드에서 텍스트를 전송할 수 있는지 여부와 상관없이 포함됩니다.) 이는 프로토콜에 의해 발생하는 프레임 오버헤드나 운영 체제 또는 네트워크 하드웨어에 의해 수행되는 버퍼링은 포함하지 않습니다.

이 간단한 예제에서 bufferedAmount 속성은 네트워크가 해당 속도를 처리할 수 있는 경우 50ms마다 한 번 업데이트를 전송하거나, 해당 속도가 너무 빠른 경우 네트워크가 처리할 수 있는 속도로 전송되도록 사용됩니다.

var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function () {
  setInterval(function() {
    if (socket.bufferedAmount == 0)
      socket.send(getUpdateData());
  }, 50);
};

bufferedAmount 속성은 네트워크가 처리할 수 있는 속도를 초과하지 않으면서 네트워크를 포화 상태로 만드는 데에도 사용할 수 있지만, 이 경우 속성 값의 변화를 신중히 모니터링해야 합니다.


binaryType getter의 단계는 thisbinary type을 반환하는 것입니다.

binaryType setter의 단계는 thisbinary type주어진 값으로 설정하는 것입니다.

사용자 에이전트는 binary type을 수신된 바이너리 데이터를 처리하는 힌트로 사용할 수 있습니다. 예를 들어, "blob"인 경우 데이터를 디스크에 저장하는 것이 안전하며, "arraybuffer"인 경우 데이터를 메모리에 유지하는 것이 더 효율적일 가능성이 높습니다. 물론 사용자 에이전트는 수신된 데이터를 메모리에 유지할지 여부를 결정하기 위해 더 미세한 휴리스틱을 사용하는 것이 권장됩니다. 예를 들어 데이터 크기나 스크립트가 마지막 순간에 속성을 변경하는 경우의 빈도 등을 기준으로 판단할 수 있습니다. 특히 이 마지막 측면은 사용자 에이전트가 데이터를 수신한 후 이벤트를 발생시키기 전에 속성이 변경될 가능성이 높기 때문에 중요합니다.

send(data) 메서드의 단계는 다음과 같습니다:
  1. thisready stateCONNECTING 이면, "InvalidStateError" DOMException를 발생시킵니다.

  2. 다음 목록에서 적절한 단계를 실행합니다:

    data가 문자열인 경우

    WebSocket 연결이 설정되었으며 WebSocket 종료 핸드셰이크가 아직 시작되지 않았으면, 사용자 에이전트는 텍스트 프레임 opcode를 사용하여 WebSocket 메시지를 전송해야 합니다. 데이터가 전송될 수 없는 경우(예: 버퍼링이 필요하지만 버퍼가 가득 찬 경우) 사용자 에이전트는 WebSocket을 가득 참으로 플래그하고 WebSocket 연결을 닫아야 합니다. 이 메서드가 문자열 인수를 사용하여 호출되었으나 예외를 발생시키지 않는 경우, 인수를 UTF-8로 표현하는 데 필요한 바이트 수만큼 bufferedAmount 속성을 증가시켜야 합니다. [UNICODE] [ENCODING] [WSP]

    dataBlob 객체인 경우

    WebSocket 연결이 설정되었으며, WebSocket 종료 핸드셰이크가 아직 시작되지 않았으면, 사용자 에이전트는 바이너리 프레임 opcode를 사용하여 WebSocket 메시지를 전송해야 합니다. 데이터가 전송될 수 없는 경우(예: 버퍼링이 필요하지만 버퍼가 가득 찬 경우) 사용자 에이전트는 WebSocket을 가득 참으로 플래그하고 WebSocket 연결을 닫아야 합니다. 전송할 데이터는 Blob 객체가 나타내는 원시 데이터입니다. 예외를 발생시키지 않는 Blob 인수를 사용하여 이 메서드를 호출하는 경우 bufferedAmount 속성이 Blob 객체의 원시 데이터 크기(바이트 단위)만큼 증가해야 합니다. [WSP] [FILEAPI]

    dataArrayBuffer 인 경우

    WebSocket 연결이 설정되었으며, WebSocket 종료 핸드셰이크가 아직 시작되지 않았으면, 사용자 에이전트는 바이너리 프레임 opcode를 사용하여 WebSocket 메시지를 전송해야 합니다. 데이터가 전송될 수 없는 경우(예: 버퍼링이 필요하지만 버퍼가 가득 찬 경우) 사용자 에이전트는 WebSocket을 가득 참으로 플래그하고 WebSocket 연결을 닫아야 합니다. 전송할 데이터는 ArrayBuffer 객체가 나타내는 버퍼에 저장된 데이터입니다. 예외를 발생시키지 않는 ArrayBuffer 인수를 사용하여 이 메서드를 호출하는 경우 bufferedAmount 속성이 ArrayBuffer 길이(바이트 단위)만큼 증가해야 합니다. [WSP]

    dataArrayBufferView 인 경우

    WebSocket 연결이 설정되었으며, WebSocket 종료 핸드셰이크가 아직 시작되지 않았으면, 사용자 에이전트는 바이너리 프레임 opcode를 사용하여 WebSocket 메시지를 전송해야 합니다. 데이터가 전송될 수 없는 경우(예: 버퍼링이 필요하지만 버퍼가 가득 찬 경우) 사용자 에이전트는 WebSocket을 가득 참으로 플래그하고 WebSocket 연결을 닫아야 합니다. 전송할 데이터는 ArrayBuffer 객체의 버퍼에서 data가 참조하는 섹션에 저장된 데이터입니다. 예외를 발생시키지 않는 이 유형의 인수를 사용하여 이 메서드를 호출하는 경우 bufferedAmount 속성이 data 버퍼 길이(바이트 단위)만큼 증가해야 합니다. [WSP]


다음은 이벤트 핸들러(및 해당 이벤트 핸들러 이벤트 유형)로, 이벤트 핸들러 IDL 속성으로 구현하는 WebSocket 인터페이스를 구현하는 모든 객체에서 지원해야 합니다:

이벤트 핸들러 이벤트 핸들러 이벤트 유형
onopen open
onmessage message
onerror error
onclose close

4. 프로토콜에서의 피드백

WebSocket 연결이 설정되었을 때, 사용자 에이전트는 작업을 대기열에 추가하여 다음 단계를 실행해야 합니다:

  1. ready stateOPEN (1)으로 변경합니다.

  2. extensions 속성 값을 사용 중인 확장으로 변경합니다. 단, null 값이 아닌 경우에만 해당합니다. [WSP]

  3. protocol 속성 값을 사용 중인 하위 프로토콜로 변경합니다. 단, null 값이 아닌 경우에만 해당합니다. [WSP]

  4. 이벤트를 발생시키며, 이벤트 이름은 open이고, WebSocket 객체에서 발생합니다.

위 알고리즘은 작업으로 대기열에 추가되므로, WebSocket 연결이 설정되는 것과 스크립트가 open 이벤트에 대한 이벤트 리스너를 설정하는 것 사이에 경쟁 조건이 없습니다.


WebSocket 메시지가 수신되었을 때, 해당 메시지의 유형 type과 데이터 data가 함께 사용자 에이전트는 작업을 대기열에 추가하여 다음 단계를 실행해야 합니다: [WSP]

  1. ready stateOPEN (1)이 아니면, 반환합니다.

  2. dataForEventtypebinary type에 따라 결정합니다:

    type이 데이터가 텍스트임을 나타내는 경우

    data를 포함하는 새 DOMString

    type이 데이터가 바이너리임을 나타내고 binary type"blob"인 경우

    data를 원시 데이터로 나타내는 새 Blob 객체, 해당 WebSocket 객체의 관련 Realm에서 생성됨 [FILEAPI]

    type이 데이터가 바이너리임을 나타내고 binary type"arraybuffer"인 경우

    data를 포함하는 새 ArrayBuffer 객체, 해당 WebSocket 객체의 관련 Realm에서 생성됨

  3. 이벤트를 발생시키며, 이벤트 이름은 message이고, WebSocket 객체에서 발생하며, MessageEvent를 사용하고, origin 속성은 WebSocket 객체의 urlorigin직렬화로 초기화되며, data 속성은 dataForEvent로 초기화됩니다.

사용자 에이전트는 작업을 실행하기 전에 위 단계를 효율적으로 수행할 수 있는지 확인하도록 권장되며, 준비 중인 버퍼와 관련하여 다른 작업 대기열에서 작업을 선택할 수 있습니다. 예를 들어, 데이터가 도착했을 때 binary type이 "blob"인 경우 사용자 에이전트가 데이터를 디스크로 스풀링했지만, 위와 같은 특정 메시지의 작업을 실행하기 바로 전에 스크립트가 binary type을 "arraybuffer"로 변경한 경우, 사용자 에이전트는 해당 작업을 실행하기 전에 데이터를 RAM으로 다시 페이지 처리하는 것이 좋으며, 이는 ArrayBuffer 객체를 생성하는 동안 메인 스레드가 멈추는 것을 방지하기 위함입니다.

다음은 텍스트 프레임의 경우 message 이벤트에 대한 핸들러를 정의하는 예제입니다:

mysocket.onmessage = function (event) {
  if (event.data == 'on') {
    turnLampOn();
  } else if (event.data == 'off') {
    turnLampOff();
  }
};

여기서 프로토콜은 매우 단순하며, 서버는 단순히 "on" 또는 "off" 메시지를 전송합니다.


WebSocket 종료 핸드셰이크가 시작되었을 때, 사용자 에이전트는 작업을 대기열에 추가하여 ready stateCLOSING (2)으로 변경해야 합니다. (close() 메서드가 호출된 경우, 이 작업이 실행될 때 ready state는 이미 CLOSING (2)으로 설정되어 있을 것입니다.) [WSP]


WebSocket 연결이 닫혔을 때, 깨끗하게 닫혔을 수도 있고(cleanly), 사용자 에이전트는 작업을 대기열에 추가하여 다음 하위 단계를 실행해야 합니다:

  1. ready stateCLOSED (3)으로 변경합니다.

  2. 사용자 에이전트가 WebSocket 연결 실패를 수행해야 했거나, WebSocket 연결이 닫혔을 때 가득 참으로 플래그된 경우 이벤트를 발생시키며, 이벤트 이름은 error이고, WebSocket 객체에서 발생합니다. [WSP]

  3. 이벤트를 발생시키며, 이벤트 이름은 close이고, WebSocket 객체에서 발생하며, CloseEvent를 사용하고, wasClean 속성은 연결이 cleanly 닫혔을 경우 true로, 그렇지 않을 경우 false로 초기화되며, code 속성은 WebSocket 연결 닫기 코드로 초기화되고, reason 속성은 BOM 없이 UTF-8 디코딩WebSocket 연결 닫기 이유에 적용한 결과로 초기화됩니다. [WSP]

사용자 에이전트는 스크립트가 다음 상황을 구별할 수 있는 방식으로 실패 정보를 전달해서는 안 됩니다:

이 모든 경우, WebSocket 연결 닫기 코드WebSocket Protocol에 의해 요구되는 대로 1006이어야 합니다. [WSP]

스크립트가 이러한 경우를 구별할 수 있도록 허용하면 공격 준비를 위해 사용자의 로컬 네트워크를 탐지할 수 있도록 허용할 수 있습니다.

특히, 이는 코드 1015가 사용자 에이전트에 의해 사용되지 않음을 의미합니다(물론 서버가 닫기 프레임에서 이를 잘못 사용하는 경우는 제외합니다).


이 섹션에서 대기열에 추가된 모든 작업작업 소스WebSocket 작업 소스입니다.

5. 핑 및 퐁 프레임

WebSocket 프로토콜은 keep-alive, 하트비트, 네트워크 상태 탐색, 지연 시간 측정 등을 위해 사용할 수 있는 Ping 및 Pong 프레임을 정의합니다. 현재 API에서는 이를 노출하지 않습니다.

사용자 에이전트는 원하는 경우 Ping 및 요청되지 않은 Pong 프레임을 보낼 수 있습니다. 예를 들어, 로컬 네트워크 NAT 매핑을 유지하거나 실패한 연결을 감지하거나 사용자에게 지연 시간 메트릭을 표시하려는 시도에서 이를 사용할 수 있습니다. 사용자 에이전트는 서버를 지원하기 위해 Ping 또는 요청되지 않은 Pong을 사용해서는 안 됩니다. 서버는 서버의 필요에 따라 적절한 시기에 Pong을 요청할 것으로 가정합니다.

6. CloseEvent 인터페이스

WebSocket 객체는 CloseEvent 인터페이스를 close 이벤트에 사용합니다:

[Exposed=(Window,Worker)]
interface CloseEvent : Event {
  constructor(DOMString type, optional CloseEventInit eventInitDict = {});

  readonly attribute boolean wasClean;
  readonly attribute unsigned short code;
  readonly attribute USVString reason;
};

dictionary CloseEventInit : EventInit {
  boolean wasClean = false;
  unsigned short code = 0;
  USVString reason = "";
};
event . wasClean

연결이 정상적으로 종료된 경우 true를 반환하고, 그렇지 않으면 false를 반환합니다.

event . code

서버에서 제공한 WebSocket 연결 종료 코드를 반환합니다.

event . reason

서버에서 제공한 WebSocket 연결 종료 이유를 반환합니다.

wasClean 속성은 초기화된 값을 반환해야 합니다. 이는 연결이 정상적으로 종료되었는지 여부를 나타냅니다.

code 속성은 초기화된 값을 반환해야 합니다. 이는 서버에서 제공한 WebSocket 연결 종료 코드를 나타냅니다.

reason 속성은 초기화된 값을 반환해야 합니다. 이는 서버에서 제공한 WebSocket 연결 종료 이유를 나타냅니다.

7. 가비지 컬렉션

WebSocket 객체의 ready state가 마지막으로 이벤트 루프1단계에 도달했을 때 CONNECTING (0)로 설정된 상태라면, open 이벤트, message 이벤트, error 이벤트, 또는 close 이벤트에 대한 이벤트 리스너가 등록되어 있는 경우 가비지 컬렉션되지 않아야 합니다.

WebSocket 객체의 ready state가 마지막으로 이벤트 루프1단계에 도달했을 때 OPEN (1)로 설정된 상태라면, message 이벤트, error, 또는 close 이벤트에 대한 이벤트 리스너가 등록되어 있는 경우 가비지 컬렉션되지 않아야 합니다.

WebSocket 객체의 ready state가 마지막으로 이벤트 루프1단계에 도달했을 때 CLOSING (2)로 설정된 상태라면, error 또는 close 이벤트에 대한 이벤트 리스너가 등록되어 있는 경우 가비지 컬렉션되지 않아야 합니다.

WebSocket 객체가 전송 대기 데이터가 있는 설정된 연결 상태라면 가비지 컬렉션되지 않아야 합니다. [WSP]

만약 WebSocket 객체가 연결이 여전히 열려 있는 동안 가비지 컬렉션된다면, 사용자 에이전트는 WebSocket 종료 핸드셰이크를 시작해야 하며, Close 메시지에 대한 상태 코드는 없어야 합니다. [WSP]


만약 사용자 에이전트가 사라지게 해야 한다WebSocket 객체(이는 Document 객체가 사라질 때 발생합니다)라면, 사용자 에이전트는 다음 목록에서 첫 번째로 적절한 단계를 따라야 합니다:

WebSocket 연결이 아직 설정되지 않았다면 [WSP]

WebSocket 연결 실패를 수행합니다. [WSP]

WebSocket 종료 핸드셰이크가 아직 시작되지 않았다면 [WSP]

WebSocket 종료 핸드셰이크를 시작하며, WebSocket Close 메시지에 사용할 상태 코드는 1001로 설정합니다. [WSP]

그 외의 경우

아무것도 하지 않습니다.

감사의 글

2021년에 이 표준이 작성되기 전까지, 여기의 내용은 HTML 표준Fetch 표준에서 관리되었습니다. 명세 개발에 도움을 준 해당 저장소의 모든 기여자들, 특히 각각의 원저자인 Ian Hickson과 Anne van Kesteren에게 감사드립니다.

WebSockets 표준이 만들어진 이후의 기여에 대해 devsnek과 평야유 (Yutaka Hirano) 에게 감사드립니다.

이 표준은 Adam Rice (Google, ricea@chromium.org)가 작성하였습니다.

지적 재산권

저작권 © WHATWG (Apple, Google, Mozilla, Microsoft). 이 작업은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스에 따라 라이선스가 부여됩니다. 소스 코드에 통합된 부분이 있는 경우, 해당 부분은 BSD 3-Clause 라이선스에 따라 소스 코드 내에서 라이선스가 부여됩니다.

이것은 현행 표준입니다. 특허 검토 버전에 관심이 있는 분들은 현행 표준 검토 초안을 확인하시기 바랍니다.

색인

이 명세서에서 정의된 용어

참조로 정의된 용어

참고 자료

규범적 참고 자료

[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ENCODING]
Anne van Kesteren. 인코딩 표준. 현행 표준. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 표준. 현행 표준. URL: https://fetch.spec.whatwg.org/
[FILEAPI]
Marijn Kruisselbrink. 파일 API. URL: https://w3c.github.io/FileAPI/
[HSTS]
J. Hodges; C. Jackson; A. Barth. HTTP 엄격한 전송 보안 (HSTS). 2012년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6797
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[UNICODE]
유니코드 표준. URL: https://www.unicode.org/versions/latest/
[URL]
Anne van Kesteren. URL 표준. 현행 표준. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WSP]
I. Fette; A. Melnikov. 웹소켓 프로토콜. 2011년 12월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6455

IDL 색인

enum BinaryType { "blob", "arraybuffer" };

[Exposed=(Window,Worker)]
interface WebSocket : EventTarget {
  constructor(USVString url, optional (DOMString or sequence<DOMString>) protocols = []);
  readonly attribute USVString url;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSING = 2;
  const unsigned short CLOSED = 3;
  readonly attribute unsigned short readyState;
  readonly attribute unsigned long long bufferedAmount;

  // networking
  attribute EventHandler onopen;
  attribute EventHandler onerror;
  attribute EventHandler onclose;
  readonly attribute DOMString extensions;
  readonly attribute DOMString protocol;
  undefined close(optional [Clamp] unsigned short code, optional USVString reason);

  // messaging
  attribute EventHandler onmessage;
  attribute BinaryType binaryType;
  undefined send((BufferSource or Blob or USVString) data);
};

[Exposed=(Window,Worker)]
interface CloseEvent : Event {
  constructor(DOMString type, optional CloseEventInit eventInitDict = {});

  readonly attribute boolean wasClean;
  readonly attribute unsigned short code;
  readonly attribute USVString reason;
};

dictionary CloseEventInit : EventInit {
  boolean wasClean = false;
  unsigned short code = 0;
  USVString reason = "";
};

MDN

CloseEvent/CloseEvent

In all current engines.

Firefox11+Safari6+Chrome16+
Opera12.1+Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

CloseEvent/code

In all current engines.

Firefox8+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

CloseEvent/reason

In all current engines.

Firefox8+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

CloseEvent/wasClean

In all current engines.

Firefox8+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

CloseEvent

In all current engines.

Firefox8+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android8+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/WebSocket

In all current engines.

Firefox11+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/binaryType

In all current engines.

Firefox11+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/bufferedAmount

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/close

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/close_event

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/error_event

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/extensions

In all current engines.

Firefox8+Safari6+Chrome16+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/message_event

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/open_event

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/protocol

In all current engines.

Firefox7+Safari6+Chrome15+
Opera12.1+Edge79+
Edge (Legacy)12+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/readyState

In all current engines.

Firefox7+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/send

In all current engines.

Firefox18+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket/url

In all current engines.

Firefox7+Safari6+Chrome18+
Opera12.1+Edge79+
Edge (Legacy)12+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

WebSocket

In all current engines.

Firefox11+Safari5+Chrome5+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+