Wednesday 14 February 2018

Sec websocket protocol binary options


이 장에서는 응답 성이 뛰어난 HTML5 WebSocket으로 업그레이드하는 방법에 대해 설명합니다. 기존 레거시 웹 네트워킹에 대한 간략한 개요로 시작한 다음 WebSocket을 사용하는 이유와 방법을 학습합니다. WebSocket 프로토콜은 문자 그대로 오버 헤드가 없음을 보여줍니다 에 비해 당신은 WebSocket을 사용하여 다음과 같은 유형의 응용 프로그램을 개발할 수 있습니다. 라이브 거래 경매 스포츠 알림. 살아있는 공동 작성. 웹을 통한 의료 장비 제어. 멀티 플레이어 온라인 게임. 사회적 스트림의 실시간 업데이트. 다음 버전의 Save the Child 애플 리케이션, 우리는 온라인 경매 통신 레이어를 구현하기 위해 WebSocket을 사용할 것입니다. 목표는 개인과 기업이 어린이가 만든 수제 예술과 공예품을 구입하도록하는 것입니다. 모든 수익금은 Save the Child로 이동합니다. 목표는 보도록하는 것입니다. 웹에서 클라이언트 - 서버 통신을위한 프로토콜을 변경했을 때의 장점은 네트웍을 모니터링하여 정기적으로 WebSocket의 장점을 분명히 볼 수 있습니다 이 장을 지원하는 모든 서버 측 기능은 Java EE 7 사양의 일부인 WebSocket 참조 구현을위한 Java API를 사용하여 Java로 작성됩니다. GlassFish 응용 프로그램 서버 릴리스 Java를 모르면이 서버 측 설치를 WebSocket 프로토콜을 지원하는 서비스로 처리하십시오. 서버 측으로 들어가기를 원하는 Java 개발자는 소스 코드와 간단한 설명을 일부 제공합니다 이 책과 함께 제공되는 코드 샘플을 살펴보십시오. 우리는 서버 전송 이벤트와 WebSocket을 사용한 서버 측 데이터 푸시를 비교 및 ​​비교합니다. 또한 WebSocket 애플리케이션을 간소화 할 수있는 Portal 및 Atmosphere와 같은 선택한 프레임 워크에 대한 간략한 개요를 볼 수 있습니다 니어 실시간 응용 프로그램을 사용합니다. 프로토콜은 오늘날의 웹 응용 프로그램의 단일 언어이며, 클라이언트 - 서버 통신은 요청 - 레포 nse 패러다임 낮은 수준에서 웹 브라우저는 각 세션에 대해 TCP IP 연결을 설정합니다. 현재 개발자가 브라우저 - 서버 통신 폴링, 긴 폴링 및 스트리밍에 사용하는 세 가지 기본 옵션이 있습니다. 이 옵션은 반이중 a 실시간 행동을 시뮬레이트하기위한 단방향 거리 프로토콜 실시간으로 우리는 어떤 사건이 일어날 때 반응 할 수있는 능력을 의미합니다. 각자 토론합니다. 클라이언트 코드를 폴링하면 미리 설정된 간격에 따라 서버에 요청이 전송됩니다. 예를 들어, JavaScript setInterval 함수를 사용하여 요청한 데이터가 아직 준비되지 않은 경우 폴링에 나와있는 것처럼 일부 서버 응답이 비어 있습니다. 예를 들어, 온라인 경매를 실행하고 업데이트 된 입찰을 보려는 요청을 보내는 경우, 누군가가 새로운 입찰을하지 않는 한 당신은 어떤 데이터도받지 못합니다. 차 뒷좌석에 앉아서 매분마다 아이를 구경하십시오. 우리가 아직 도착 했습니까? 그리고 정중하게 대답합니다. n empty server response이 아이를위한 유용한 페이로드는 없지만 일부 메타 데이터 폴링을 계속 수신하면 데이터로드가없는 자세한 응답 헤더를 수신 할 수 있습니다. 드라이버의 생각을 혼란시키지 않고 서버가 다른 책임을 수행하지 못하게 할 수 있습니다. 그림 1 폴링 긴 폴링을 참조하십시오. 긴 폴링을 참조하십시오. 클라이언트가 폴링과 비슷하게 시작하여 클라이언트가 서버에 요청을 보냅니다. 그러나이 경우 빈 응답을 다시 보내는 대신 서버는 클라이언트의 데이터를 사용할 수있을 때까지 기다립니다. 지정된 시간 간격 내에 사용할 수없는 경우 서버는 클라이언트에 빈 응답을 보내고 연결을 닫은 후 다시 연결합니다. 폴링과 긴 폴링을 비교하는 비유를 하나 더 제공합니다. 건물의 최상층에있는 파티를 상상해보십시오. 매분마다 올라가고 손님 중 한 명이 담배 피우기 위해 내려 가고 싶어하는 경우를 대비하여 스마트 엘리베이터가 작동합니다. 아무도 엘리베이터에 들어 가지 않으면 지상으로 간다. 그리고 60 초 만에 다시 올라간다 이것은 폴링 시나리오 다. 그러나 만일 누군가가 실제로 내려 가기를 결정하거나 기다리기가 어려워 질 때까지이 엘리베이터가 올라서 기다렸다면 우리는 긴 폴링 모드라고 부를 수있다. 관점, 긴 폴링 모드는 느린 응답의 서버를 다루는 것처럼 보일 수 있습니다. 따라서이 기술을 Hanging GET이라고도합니다. 사람들이 항목에 입찰 할 때 가격을 자동으로 수정하는 온라인 경매를 볼 때, 서버가 데이터를 사용자에게 푸시하는 것처럼 보입니다. 그러나이 기능은 실제 서버 측 데이터 푸시가 아닌 긴 폴링을 사용하여 구현되지만 기회는 있습니다. 그림 2 긴 폴링. 스트리밍을 볼 때 클라이언트는 데이터 요청을 보냅니다. 서버가 데이터 준비를 마자 마자 연결을 닫지 않고 응답 객체에 점점 더 많은 데이터를 추가하기 시작합니다. 서버는 클라이언트에 데이터를 푸시합니다. 예를 들어 YouTube에서 동영상을 요청하면 연결이 끊어지지 않고 프레임 이후에 데이터 프레임이 스트리밍됩니다. 그림 3 스트리밍. HTML5 API의 서버를 지원하지 않는 레거시 브라우저의 경우 폴링 및 스트리밍을 대체로 사용할 수 있습니다 - sent 이벤트 및 WebSocket. ServerSend 이벤트를 구현합니다. WebSocket 프로토콜로 들어가기 전에 서버에서 보낸 이벤트를 구현하는 표준화 된 방법에 익숙해집니다. SSE World Wide Web Consortium W3C는 웹 브라우저 용 API를 게시하여 서버에 의해 보내지는 이벤트를 구독하는 모든 현대의 브라우저는 DOM 이벤트의 형태로 도착하는 이벤트를 처리 할 수있는 EventSource 객체를 지원합니다. 이것은 request-respo가 아닙니다 nse 패러다임이 아니라 서버에서 브라우저로의 단방향 데이터 푸시 서버가 보낸 이벤트 구독은 웹 브라우저가 서버가 보낸 이벤트를 구독하고 청취 할 수있는 방법을 보여줍니다. 예제 1 서버가 보낸 이벤트 구독. 웹 소켓 핸드 셰이크. 모든 네트워크 통신 이 핸드 셰이크는 WebSocket 프로토콜로 연결을 업그레이드합니다. 메시지 기반 통신으로 업그레이드합니다. 이 장의 뒷부분에 나오는 메시지를 토론합니다. TCP로 시작하는 대신 프로토콜이 필요합니다. 그 이유는 WebSocket이 동일한 포트 80 및 443에서 작동하기 때문이며, 엔터프라이즈 방화벽이 임의의 소켓 연결을 허용하지 않을 수 있기 때문에 브라우저의 요청이 동일한 포트를 통해 라우팅된다는 중요한 이점이 있습니다 보안상의 이유로 또한 많은 기업 네트워크는 특정 발신 포트 만 허용하고 포트는 일반적으로 소위 말하는 흰색 목록에 포함됩니다. Browser Networking. by Ilya Grigorik O Reilly는 TCP에 대한 자세한 정보를 제공합니다. 프로토콜 업그레이드는 클라이언트 요청에 의해 시작되며 요청과 함께 특수 키를 전송합니다. 서버는이 요청을 처리하고 업그레이드 확인을 다시 전송합니다. WebSocket 연결은 WebSocket을 지원하는 끝점에서만 설정할 수 있습니다. 클라이언트의 요청에서 핸드 셰이크가 어떻게 보이는지 확인할 수 있습니다. 이 클라이언트는 프로토콜 업그레이드를위한 GET 요청을 보냅니다. Sec-WebSocket-Key는 임의의 바이트 집합입니다. 서버는이 바이트를 취해이 키에 특별한 전역 고유 식별자 GUID 문자열을 추가합니다. 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 그런 다음 Secure Hash Algorithm SHA1 해시를 만들고 Base64 인코딩을 수행합니다. 결과 바이트 문자열을 사용해야합니다 이 문자열은 WebSocket 프로토콜을 이해하지 못하는 네트워크 끝점에서 사용되지 않습니다. 그런 다음이 값은 Sec-Web에 복사됩니다 Socket-Accept 헤더 필드 서버는 값을 계산하고 프로토콜 업그레이드를 확인하여 응답을 되돌려 보냅니다. WebSocket 프로토콜은 400 Bad Request 오류 코드를 사용하여 실패한 업그레이드 신호를 보냅니다. 핸드 셰이크에는 서브 프로토콜 요청과 WebSocket 버전 정보, 다른 임의의 헤더를 포함 할 수 없습니다. 승인 정보를 전송할 수 없습니다. 이 문제를 해결하는 방법은 두 가지가 있습니다. 예를 들어 첫 번째 요청으로 인증 정보를 전송하거나, 고유 한 clientId를 요청 헤더 또는 HTML 래퍼의 일부로 전달할 수 있습니다 또는 초기 핸드 셰이크 중에 쿼리 매개 변수로 URL에 넣으십시오. 다음 예제를 고려하십시오. WebSocket Framework를 사용하십시오. 바닐라 WebSocket API를 사용하여 직접 추가 코딩 작업을 수행해야합니다. 예를 들어, 클라이언트 브라우저가 기본적으로 WebSocket을 지원하기 때문에 코드가 유산으로 돌아가는 지 확인해야합니다. 좋은 소식은 이 프레임 워크는 개발 시간을 단축시켜보다 적은 코드로 더 많은 작업을 수행 할 수있게 해줍니다. 이 섹션에서는 WebSocket을 사용하여 웹 애플리케이션 개발을 간소화 할 수있는 두 가지 프레임 워크에 대해 간략하게 설명합니다. 현재 웹 브라우저와 서버에서 가장 잘 지원되는 전송 도구 인 반면 개발자는 사용 된 메커니즘의 내부를 알지 못합니다. 개발자는 응용 프로그램 논리를 프로그래밍하고 데이터 전송이 필요할 때 프레임 워크 API를 호출하는 데 집중할 수 있습니다. 포털은 서버에 무관심한 JavaScript 라이브러리입니다. WebSocket 프로토콜을 활용하고 다양한 전송을위한 통합 API를 제공합니다. 폴링, 스트리밍, WebSocket 현재 다음 프로젝트에 WebSocket을 사용하기로 결정한 후 Internet Explorer 9 또는 이전 버전과 같이 이전 버전의 브라우저를 계속 사용하는 사용자를 기억하십시오. 이 버전에서는 WebSocket을 기본적으로 지원하지 않습니다. 그럴 경우 응용 프로그램을 정상적으로 사용할 수있는 최상의 네트워킹 대안으로 적절하게 대체해야합니다. 가능한 모든 브라우저와 버전을 지원하는 코드를 수동으로 작성해야합니다. 특히 다른 플랫폼의 코드를 테스트하고 유지 관리하는 데 많은 시간이 필요합니다. Simple 포털을 가진 비동기 웹 응용 프로그램 클라이언트. 예 4 포털이있는 간단한 비동기 웹 응용 프로그램 클라이언트. 사람이 읽을 수있는 형식입니다. 대부분의 브라우저에는 기본 제공 XML 판독기 및 파서가 있습니다. XSD 또는 XML 스키마는 XSD 또는 DTD 스키마에 대해 유효성을 검사 할 수 있습니다. XML 문서의 구조, 내용 및 의미를 정의하기 때문에 유용한 언어 기능 인간의 가독성 때문에 XML 스키마는 소프트웨어 개발자가 아닌 사람들이 사용할 수 있으며 다른 프로그래밍으로 작성된 시스템을 통합하는 데 사용할 수 있습니다 죄수는 다음과 같습니다. XML은 매우 장황합니다. 고객의 이름을 보내려면이 custname Mary custname과 같은 것이 필요합니다. 클라이언트의 XML 유효성 검사는 복잡한 작업입니다. 현재로서는 XSD 또는 DTD. XML을 기반으로 프로그래밍 방식으로 유효성을 검사하는 플랫폼 독립적 솔루션이나 API는 없습니다. Elliotte Rusty Harold 및 W Scott Means O Reilly is JSON은 JavaScript Object Notation의 약자로 JSON은 모든 웹 브라우저에서 인코딩 및 디코딩 할 수있는 구조화 된 데이터를 표현합니다. 데이터를 직렬화하는 보편적 인 방법으로서의 웹 커뮤니티 앞에서 언급했듯이 XML보다 데이터를 표현하는 데 더 간단한 방법을 제공하며 모든 최신 웹 브라우저는 JSON 데이터를 이해하고 파싱 할 수 있습니다. Google 프로토콜 버퍼. Google 프로토콜 버퍼 또는 protobuf는 구조화 된 데이터 직렬화를위한 언어 및 플랫폼 중립적 인 확장 가능한 메커니즘 데이터를 구조화하는 방법을 정의한 후에 특수 생성 된 소스 코드를 사용하여 쉽게 작성하고 읽을 수 있습니다 다양한 데이터 스트림에서 구조화 된 데이터를 개발할 수 있습니다. 개발자는 다양한 환경에서 동일한 스키마를 사용할 수 있습니다. 개발자는 파일에 프로토콜 버퍼 메시지 유형을 정의하여 직렬화 가능 정보가 구조화되어야하는 방법을 지정해야합니다. 각 프로토콜 버퍼 메시지는 , 일련의 이름 값 쌍을 포함하는 정보의 논리적 레코드이 프로토콜 버퍼 메시지 파일은 언어에 구애받지 않습니다. protoc 유틸리티는 proto 파일을 컴파일하고 예를 들어 파일 및 언어 관련 아티팩트를 생성합니다. 예를 들어, 저장을위한 프로토콜 버퍼 proto 파일을 작성할 수 있습니다 기부 메시지에 대한 프로토콜 버퍼에 표시된 것처럼 기증자에 대한 정보를 나타낼 자식. 예제 5 기증 메시지 용 프로토콜 버퍼. 기부 메시지의 직렬화 - 소멸에 필요한 모든 코드가 포함됩니다. 생성 된 코드를 게시하지 않습니다. 여기, 하지만 이전 메시지 선언에서 직접이 코드를 생성 할 수 있습니다. protobuf wiki 페이지에서 원하는 언어에 대한 protobuf 컴파일러 protobuf 기술에 익숙해 지려면 설명서 및 자습서를 확인하십시오. 프로토 타입 프로가 있습니다. 메시지가 압축되고 최적화 된 바이너리 형식으로 인코딩됩니다. 인코딩 형식에 대한 자세한 내용은에서 확인할 수 있습니다. 프로토콜 버퍼 문서화 웹 사이트입니다. Google은 광범위한 프로그래밍 언어를위한 프로토콜 버퍼를 지원합니다. Java, C, Python 개발자 커뮤니티에서도 지원합니다. 프로토콜 버퍼의 사용은 잘 문서화되어 있습니다. 다음은 몇 가지 단점입니다. 형식은 사람이 읽을 수 없습니다. protobuf는 압축 적이지만 인코딩 알고리즘으로 많은 숫자 값이 전송되는 경우 특히 JSON은 기본적으로 JavaScript에서 지원되므로 추가 파서 구현이 필요하지 않습니다. Protobuf에는 바이너리 형식을 지원하는 웹 브라우저가 필요하며, 모든 브라우저가 아직 수행하지는 않습니다. 사용할 수있는 브라우저에서 원시 이진 데이터를 지원하는 브라우저를 찾을 수 있습니다. Proxies와 함께 WebSocket을 사용합니다. WebSocket 프로토콜 자체는 프록시 서버, 방화벽 및 컨텐츠 필터와 같은 중개자를 인식하지 못합니다. 프록시 서버는 일반적으로 컨텐츠 캐싱, 보안 및 엔터프라이즈 컨텐츠 필터링에 사용됩니다. 프로토콜 업그레이드는 항상 지원했지만 많은 프록시 서버는 사양 일부를 무시한 것 같습니다. WebSocket이 나올 때까지는 업그레이드 속성이 사용되지 않았습니다. WebSocket과 같이 오래 지속되는 웹 응용 프로그램과 관련된 문제는 프록시 서버가 스트리밍 또는 유휴 WebSocket 연결이 응답하지 않는 서버에 연결하려고 시도하기 때문에 연결을 닫도록 선택합니다. 또한 브라우저가 응답 전체를 수신해야한다고 가정 할 때 프록시 서버가 암호화되지 않은 응답을 버퍼링 할 수 있습니다. WebSocket 지원 애플리케이션은 프록시를 처리해야하며 Google의 Peter Lubbers, WebSocket 및 Proxy Servers의 포괄적 인 연구 보고서를 확인해야합니다. 이 책의 저자는 NGINX를 사용하여 정적 리소스를 제공하는 대단히 인기있는로드 밸런서 및 프록시와 서버를 사용합니다. 이미지 및 텍스트 파일을 관리하고 Java 서버 간의로드 균형을 조정하며 SSL 오프로드를 수행하여 웹 브라우저의 요청을 N GINX는 연결 당 하나의 작업자 스레드를 사용하는 기존 웹 서버와 달리 수천 명의 동시 사용자를 지원하기 위해 적은 수의 스레드를 사용합니다. 최근 NGINX는 WebSocket 프로토콜을 지원하기 시작했습니다. 경매를 추가하여 Child를 저장합니다. Save the Child 애플리케이션에서 WebSocket을 구현하려는 욕구를 자극하십시오. 목표는 사람들이 다양한 상품을 입찰하고 구매하고 수익금을 저축 할 수 있도록 경매를 만드는 것입니다. Child Auctions는 특정 경매 항목에 관심이있는 모든 사람들에게 실시간 커뮤니케이션이 필요합니다. 과 입찰 또는 우승에 대해 즉시 통보해야합니다. 따라서 WebSocket을 경매의 변경 사항에 대한 입찰 및 알림 제공 수단으로 사용합니다. 경매를 시작하기 위해 사용자는 메뉴에서 경매 옵션을 선택해야합니다. 처음에는 두 개의 모듈 만로드됩니다. 경매 참여를 결정하는 사용자는 소수에 불과하며, 건축 적 측면에서 볼 때 보기는 경매를 지원하는 코드가 사용자가 경매를 방문하도록 선택한 경우에만 요청시로드되어야 함을 의미합니다. 따라서이 코드를로드 가능한 모듈로 작성해야하며 웹 응용 프로그램이 이 장에서 우리는 RequireJS를 계속 사용합니다. 모듈화를위한 프레임 워크로 모듈화 프로젝트를 모듈화하십시오. RequireJS를 사용하여 사용자가 요청한 경우에만 모듈을 지연로드합니다. 이 책은 사용자 개발에 관한 것입니다. 인터페이스 및 웹 애플리케이션의 클라이언트 측에 대한 정보를 제공하므로 서버 측 구현의 모든 세부 사항을 다루지는 않지만 서버 측 코드를 다운로드 할 수있게 할 것입니다. 서버를 계속 가동 시켜서 다음과 같이 UI를 테스트 할 수 있습니다. 이 섹션의 주요 목표는 WebSocket을 사용하여 서버와 경매 데이터를 교환하고 클라이언트 측에서 처리하는 방법을 보여주는 것입니다. Java 응용 프로그램 서버 인 GlassFish 4를 사용합니다. Java EE 7 사양의 구현. 이 책의 저자는 Java 개발자이며 우리는 Webcast Server API를 강조하는 screencast를 기록했습니다. Java 개발자가 아닌 경우 자신을 위해 어떤 WebSocket 서버가 있는지 알아야 할 수도 있습니다. 좋아하는 프로그래밍 언어 또는 플랫폼. modularizingjavascriptprojects는 RequireJS 프레임 워크를 사용하여 웹 응용 프로그램을 여러 모듈로 분할하는 방법을 보여줍니다. 이 프로젝트를 기반으로 사용하여 프로젝트 -16-websocket-auction 새 모듈을 만듭니다. WayToGive 모듈은 옥션 WayToGive 모듈을 지원하는 새 모듈을 추가합니다. WayToGive 모듈의 코드입니다. Example 6 WayToGive 모듈입니다. 응용 프로그램이 시작된 후 RequireJS는 처음에는 두 개의 모듈 만로드되는 것처럼 필수 모듈, 로그인 및 기부 만로드합니다. Google 크롬 개발자 도구 콘솔에서 로그인 및 기부 모듈이 성공적인로드에 대해보고합니다. Save the Child 응용 프로그램을 시작하는 동안 두 개의 모듈이로드됩니다. 이 모듈이 Donate Now 버튼을 클릭하면 양식이 표시되고, Login 단추를 클릭하면 ID 및 암호 필드가 표시됩니다. 4 처음에는 두 개의 모듈 만로드됩니다. 그림 5 Save the Child 응용 프로그램 시작 중에 두 개의 모듈이로드됩니다. 이제 W를 클릭하십시오. ay To Give 메뉴와 Developer Tools 콘솔에 주목하십시오. 경매 컨트롤이로드되고 렌더링 된 것을 볼 수 있습니다. WayToGive 모듈이로드 및 렌더링에 대해보고합니다. 그림 6 경매 컨트롤이로드되고 렌더링됩니다. 사용자가 웨이를 클릭하면 Give, RequireJS 프레임 워크는 WebSocket 기반 경매 모듈의 코드를로드해야 함 모듈에 제공 방법로드 모듈에서 JavaScript 파일의 코드 스 니펫을 저장합니다. 자식 저장 애플리케이션의 시작점입니다. 요청시 모듈을로드하는 방법입니다. RequireJS refresher에 대한 모듈화 javascript 프로젝트입니다. 예제 7 모듈 제공 방법로드. 요청 메시지 양식 Child Security Protocol을 저장하는 중 메시지 형식의 세부 정보를 찾을 수 있습니다. WebSocket 객체 상태 확인 WebSocket이 readyState 1을 열면, 응용 프로그램에서 메시지를 보낼 수 없다면이 코드는 콘솔에 오프라인 메시지를 기록하기 만하면됩니다. 실제로는이 메시지를 항상 사용자에게 표시해야합니다 UI 사용자가 셀룰러 또는 3G와 같은 불안정한 네트워크에서 작업하는 경우 분명히 데이터가 손실되는 것을 원하지 않습니다. 로컬 스토리지 API를 사용하는 것이 좋습니다. mockinguptheapp를 참조하여 응용 프로그램이 온라인 상태가 될 때까지 로컬에서 데이터를 유지하십시오. 사용자는 콤보 상자에서 옥션 lot을 선택하고 이미지를 볼 수 있습니다. 콘솔에는 경매 항목 목록이 들어있는 들어오는 메시지가 기록되며 콘솔에는 무엇이 표시되는지, 그림은 그림과 네트워크 탭의 내용을 보여줍니다. 두 이미지. 그림 7 콘솔은 경매 항목 목록을 포함하는 수신 메시지를 기록합니다. 그림 8 DevTools의 네트워크 기능을 사용하여 WebSocket 프레임을 모니터링 할 수 있습니다. 그림 9 구매자는 입찰 할 다른 항목을 선택할 수 있습니다. Chrome 개발자 도구 사용. WebSocket 핸드 셰이크에 설명 된 이론의 실제 사용을 검토하십시오. Chrome 개발자 도구를 사용하여 그림과 같이 초기 핸드 셰이크에 대한 정보를 모니터링 할 수 있습니다 Chrome Dev Tools 모니터링의 초기 WebSocket 핸드 셰이크 Chrome Developer Tools의 WebSocket 트래픽은 어떤면에서 요청 모니터링과 다르지 않습니다. 트래픽은 왼쪽 패널에서 WebSocket 끝점의 경로를 선택한 후 네트워크 탭에서 볼 수 있습니다. 오른쪽 하단의 WebSockets을 클릭하여 WebSocket 끝점 만 표시 오른쪽 창에서 프레임 탭을 클릭하면 클라이언트와 서버간에 교환되는 실제 프레임이 표시됩니다 (Chrome 개발자 도구의 Monitoring WebSocket 프레임 참조). 흰색 줄은 들어오는 데이터는 녹색으로 표시되거나 종이에 회색으로 표시되는 데이터는 나가는 데이터를 나타냅니다. 그림 10 Chrome DevTool의 초기 WebSocket 핸드 셰이크 그림 11 Chrome Developer Tools에서 WebSocket 프레임 모니터링. 자세한 내용을 보려면 Chrome을 Chrome의 숨겨진 URL 인 chrome net-internals로 이동하십시오. 유용한 정보를 많이 제공합니다. 그림을보고 Chromium Design Documents에서 net-internals에 대한 문서를 찾을 수 있습니다. 그림 1 2 Chrome 네트워크 내부의 초기 핸드 셰이크에 대한 세부 정보. Google 개발자 도구는 데이터의 길이 만 표시합니다. 그러나 Chrome net-internals는 WebSocket 프레임의 크기도 표시합니다. 개발자 도구 및 그물 내부, 나란히보기 net-internals 및 Developer Tools이 장의 앞부분에서 배웠 듯이 프레임의 전체 크기는 페이로드의 크기와 약간 다릅니다. 프레임 헤더에 대해 몇 바이트가 더 있음 또한 모든 보내는 메시지는 브라우저에서 마스크됩니다 WebSocket frame anatomy를 참조하십시오. 이 프레임 마스크는 프레임 자체의 일부로 서버로 전송 될 것이며 추가 32 비트 4 바이트의 오버 헤드를 생성합니다. 그림 13 소켓 연결의 세부 사항 그림 14 개발자 도구 및 net - Wireshark를 사용하여 WebSocket 프레임을 비교합니다. Wireshark는 네트워크 트래픽을 분석하기위한 강력하고 포괄적 인 모니터링 도구입니다. Wireshark 웹 사이트에서 다운로드 할 수 있습니다. WebSocket tr 로컬 호스트의 affic 왼쪽 패널에서 루프백 네트워크 인터페이스를 선택하고 시작을 클릭합니다. Wireshark 응용 프로그램 기본보기를 봅니다. 그림 15 Wireshark 응용 프로그램 기본보기. Wireshark는 모든 네트워크 활동을 캡처합니다. 현재있는 데이터 만보기 위해 필터를 설정할 수 있습니다 관심이 있습니다. WebSocket 서버 Oracle GlassFish가이 포트에서 실행되기 때문에 포트 8080에서 TCP 트래픽을 캡처하고 싶습니다. 필터 설정 필터 텍스트 입력란에 Enter를 입력하고 Apply를 클릭하십시오. 그림 16 필터 설정. 이제 Wireshark가 우리의 응용 프로그램 경매 세션을 시작하고 입찰가를 설정할 수 있습니다. 경매로 끝내면 Wireshark 창으로 돌아가서 결과를 분석 할 수 있습니다. 프로토콜 업그레이드를위한 GET 요청 및 GET 요청에서 초기 핸드 셰이크 GET 요청을 볼 수 있습니다. 프로토콜 업그레이드를 통한 GET 응답. 그림 17 프로토콜 업그레이드를위한 GET 요청. 그림 18 프로토콜 업그레이드를 통한 GET 응답. 성공적인 연결 업그레이드 후, Wire 상어가 스트림을 캡처합니다. 8080 포트에서 WebSocket의 트래픽을보고하는 방법입니다. 이 행을 마우스 오른쪽 버튼으로 클릭하고 TCP 스트림 따르기 메뉴에 표시된대로 TCP 스트림 따르기를 선택합니다. 그림 19 TCP 스트림 따르기 메뉴. 다음 화면에서 WebSocket 프레임의 세부 정보를 볼 수 있습니다. WebSocket 프레임 참조하십시오. 경매 애플리케이션이 시작된 직후이 스크린 샷을 촬영했습니다. 사용 가능한 경매 목록이있는 데이터를 볼 수 있습니다. 보내는 데이터는 빨간색으로 표시되고 들어오는 데이터는 파란색으로 표시됩니다. 그림 20 WebSocket 프레임. 에 표시된 스크린 샷 전체 ​​경매가 종료 된 후 경매가 종료되었습니다. WebSocket 연결을 통해 전송 된 모든 데이터를 볼 수 있습니다. 그림 21 전체 경매 대화. Save the Child Auction Protocol을 작성 중입니다. WebSocket이 전송 프로토콜 인 경우 클라이언트 - 서버 상호 작용에서 입찰 메시지의 형식을 지정하는 방법을 나타내는 응용 프로그램 수준 프로토콜이 필요합니다. 이것이 우리가 결정한 방법입니다. 클라이언트의 공동 de는 서버의 WebSocket 끝점에 연결합니다. 클라이언트의 코드는 현재 실행중인 경매 목록을 검색하기 위해 AUCTIONLIST 메시지를 보냅니다. 경매가 끝난 후 서버는 최종 경매 결과와 함께 메시지를 브로드 캐스팅합니다. 경매 서버에, 그 사용자는 축하 메시지를 받게됩니다 다른 참가자는 죄송합니다, 당신은 알림을 얻지 못했습니다 얻을 것이다. 이것은 거의 그것입니다 경매의 클라이언트의 측면을 구현하는 데 필요한 코드의 양을 최소화 연결 후 업그레이드가 완료되면 대부분의 처리는 WebSocket 객체의 메시지 처리기에서 수행됩니다. 이 장을 읽고 나면 WebSocket 프로토콜을 웹 응용 프로그램에서 사용할 때의 이점을 확인해야합니다. 대부분의 경우 WebSocket은 네트워크 대기 시간을 줄이고 헤더 오버 헤드를 제거하여 애플리케이션 성능 향상 WebSocket 기반 기능을 exis에 통합하는 방법을 배웠습니다. 애플리케이션 저장 WebSocket을 통해 웹 애플리케이션을 통신 할 필요가 없습니다. 애플리케이션의 성능과 응답 성을 향상시킬 때이 강력한 프로토콜을 사용하십시오. 부수적으로 Google의 네트워크 모니터링 기능을 사용하는 방법을 배웠습니다 Chrome 개발자 도구 및 WebSocket 트래픽을 감지하여 Wireshark 웹 개발자에게 가장 좋은 친구 인 모니터링 도구의 중요성을 과소 평가할 수 없습니다. 이 클래스는 WebSocket 서버를 나타내며 EventEmitter. new 콜백을 확장합니다. 호스트 바인딩 할 호스트 이름 server. port server. backlog를 바인드 할 포트 보류 중 connection. server 대기열의 최대 길이 미리 작성된 server. verifyClient 들어오는 연결의 유효성을 검증하는 데 사용할 수있는 함수 below 설명을 참조하십시오. handleProtocols 가능한 기능 WebSocket 서브 프로토콜을 처리하는 데 사용됩니다. 아래 설명을 참조하십시오. path이 path와 일치하는 연결 만 수락합니다. noServer se rver mode. clientTracking clients. perMessageDeflate를 추적 할 것인지 여부를 지정합니다. disable permessage-deflate. maxPayload 허용되는 최대 메시지 크기 (바이트)입니다. 새 서버 인스턴스를 만듭니다. 포트 서버 또는 noServer 중 하나를 제공해야하며 그렇지 않으면 오류가 발생합니다. verifyClient 가 설정되어 있지 않으면 핸드 셰이크가 자동으로 받아 들여집니다. 단일 인수가 제공되면 다음과 같습니다. origin client. req가 나타내는 Origin 헤더의 값 클라이언트가 GET request. secure를 true 또는 false로 설정하면 true입니다. 반환 값 함수의 부울은 handshake. if를 수락할지 여부를 결정합니다. verifyClient에는 두 개의 인수가 제공됩니다. 정보. 위와 같습니다. cb 정보 필드를 검사 할 때 사용자가 호출해야하는 콜백입니다. 이 콜백의 인수는 다음과 같습니다..result 핸드 셰이크를 승인 할 것인지 여부. code result가 false 일 때이 필드는 client. name에 보낼 오류 상태 코드를 결정합니다. result가 false 일 때이 필드는 이유 ph rase. handleProtocols가 설정되지 않은 경우 핸드 셰이크가 자동으로 허용됩니다. 그렇지 않으면 함수는 단일 인수를 사용합니다. protocols Sec-WebSocket-Protocol 헤더에서 클라이언트가 지정한 WebSocket 하위 프로토콜 목록입니다. 반환 값이 false이면 핸드 셰이크가 401 상태 코드로 거부 된 경우 반환 된 값은 101 응답의 Sec-WebSocket-Protocol 헤더 값을 설정합니다. perMessageDeflate는 permessage-deflate 확장의 비헤이비어를 제어하는 ​​데 사용할 수 있습니다. false 인 경우 확장을 비활성화합니다. 기본값은 true입니다. If 객체가 제공되면 확장 매개 변수입니다. serverNoContextTakeover 컨텍스트 인계를 사용할지 또는 사용하지 않습니다. clientNoContextTakeover 컨텍스트를 사용할지 여부를 클라이언트에 요청할 값 take 또는 not. serverMaxWindowBits windowBits. clientMaxWindowBits의 값 max windowBits to clients. memLevel memLevel. threshold 값보다 작은 페이로드는 압축되지 않습니다. 기본값 s 속성이 비어 있으면 제공되는 구성 또는 기본값이 사용됩니다. 조각화 된 메시지를 보낼 때 첫 번째 조각의 길이가 임계 값과 비교됩니다. 전체 message. callback에 압축이 사용되는지 결정합니다. 서버가 내부적으로 만들어지고 포트 옵션이 제공 될 때 청취 이벤트에 대한 리스너로 추가 될 수 있습니다. 핸드 셰이크가 완료되면 소켓이 WebSocket의 인스턴스입니다. 연결이 닫힙니다. 새로운 WebSocket 주소, 프로토콜, 옵션. address 연결할 connect. protocols의 URL 하위 프로토콜 목록. protocol Sec-WebSocket-protocol header. perMessageDeflate의 값 disable permessage-deflate. localAddress 네트워크 연결을위한 로컬 인터페이스. protocolVersion Sec-WebSocket - 버전 header. headers request. origin과 함께 보낼 사용자 정의 헤더가있는 객체 protocolVersio에 따라 Origin 또는 Sec-WebSocket-Origin 헤더의 값 n. agent Host. family IP 주소 패밀리의 지정된 Agent. host 값을 사용하여 호스트 이름 조회 중에 사용합니다. 4 또는 6.checkServerIdentity 서버를 확인하는 함수 hostname. rejectUnauthorized 서버 인증서 확인 또는 인증 안 함. passphrase 개인 키 또는 pfx. ciphers 사용할 암호 또는 exclude. cert 인증서 key. key 개인 키. pfx 개인 키, 인증서 및 CA certs. ca 신뢰할 수있는 인증서. perMessageDeflate 매개 변수는 서버와 동일하지만 유일한 차이점은 요청 방향입니다. 예 : serverNoContextTakeover는 서버에 요청할 값입니다. 새 WebSocket 인스턴스를 만듭니다. UNIX Domain Sockets. ws는 UNIX 도메인 소켓에 대한 요청을 지원합니다. 다음 URL 스키마를 사용하십시오. 소켓 경로와 URL 경로 사이 URL 경로가 생략 된 경우 연결이 닫힐 때 부여됩니다. 코드는 연결이 닫힌 이유를 설명하는 상태 코드를 나타내는 숫자 값입니다. d reason은 연결이 닫힌 이유를 설명하는 사람이 읽을 수있는 문자열입니다. 오류가 발생하면 적용됩니다. 여기에서 오류가 전달됩니다. 서버에서 메시지를 수신하면받습니다. 서버에서 퐁을 수신하면받습니다. 서버 응답이 예상 응답이 아닌 경우 (예 : 401 응답)이 이벤트는 유용한 정보를 추출하기 위해 응답을 읽는 기능을 제공합니다. 서버가 유효하지 않은 응답을 보내고이 이벤트에 대한 리스너가없는 경우 오류가 방출됩니다. type A string representing the event type to listen for. listener The listener to add. Register an event listener emulating the EventTarget interface. A string indicating the type of binary data being transmitted by the connection This should be one of nodebuffer , arraybuffer or fragments Defaults to nodebuffer Type fragments will emit the array of fragments as received from the sender, without copyfull concatenation, which is useful for the performance of binary p rotocols transfering large messages with multiple fragments. The number of bytes of data that have been queued using calls to send but not yet transmitted to the network. Received bytes count. code A numeric value indicating the status code explaining why the connection is being closed. reason A human-readable string explaining why the connection is closing. Initiate a closing handshake. An object containing the negotiated extensions. An event listener to be called when connection is closed The listener receives a CloseEvent named close. An event listener to be called when an error occurs The listener receives an Error instance. An event listener to be called when a message is received from the server The listener receives a MessageEvent named message. An event listener to be called when the connection is established The listener receives an OpenEvent named open. Pause the socket. mask , failSilently. data The data to send in the ping frame. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. failSilently Specifies whether or not to throw an error if the connection is not open. mask , failSilently. data The data to send in the ping frame. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. failSilently Specifies whether or not to throw an error if the connection is not open. The subprotocol selected by the server. The WebSocket protocol version used for this connection, 8 or 13.The current state of the connection This is one of the ready state constants. type A string representing the event type to remove. listener The listener to remove. Removes an event listener emulating the EventTarget interface. Resume the socket. options , callback. data The data to sendpress Specifies whether data should be compressed or not Defaults to true when permessage-deflate is enabled. binary Specifies whether data should be sent as a binary or not Default is autodetected. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. fin Specifies whether data is the last fragment of a message or not Defaults to true. callback An optional callback which is invoked when data is written out. Send data through the connection. Forcibly close the connection. The GET request sent by the client Useful for parsing authority headers, cookie headers, and other information This is only available for server clients. The URL of the WebSocket server Server clients don t have this attribute. What s different in the new WebSocket protocol. Developer Advocate in Tokyo. The WebSocket protocol specification has recently been updated to solve previous security concerns and is largely stable Below is a sum mary of the changes involved, along with some notes on current implementations. What has been changed since WebSocket HyBi 00.The protocol frame format has been changed HyBi 00 used to use 0x00 for head and 0xff for tail for each frame HyBi 10 now uses new format like following. Security issues have been addressed. Sec-WebSocket-Key and Sec-WebSocket-Accept are added in place of HyBi 00 s three keys The browser gives randomly generated number to Sec-WebSocket-Key Then, the server uses it with WebSocket protocol s specific GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 and SHA1 BASE64, etc to return Sec-WebSocket-Accept so that browser can confirm that it understands WebSocket This prevents a cross-protocol attack. On each frame, frame masking is now required This prevents cache poisoning on proxy Sec-WebSocket-Origin is added to prevent access from scripts that the service provider isn t aware of. Sec-WebSocket-Origin is added in place of HyBi 00 s Origin key to prevent access from scripts that the service provider doesn t aware of Note that this will be just Origin on HyBi 11.JS API changes. subprotocol can now be array, allowing a method signature of new WebSocket String url, Array subprotocol. attribute String. attribute Blob ArrayBuffer. Status code and reason why the connection is closed have been added to CloseEvent The close function has also been changed to accept these two arguments accordingly. Sec-WebSocket-Extensions is added Proposed extensions are. deflate-frame makes frames compressed at source and extracted at destination. x-google-mux to support multiplexing but is in early stage. Is there compatibility between HyBi 00 and HyBi 10 on both server and browser implementation. Server implementations can support both HyBi 00 and HyBi 10 by looking at the handshake header However, it is not recommended to support HyBi 00 since it s known to be vulnerable. The WebSocket JavaScript API is largely similar between old and new versions But as noted above, we don t recommend supporting HyBi 00 since it s known to be vulnerable. Which browser support HyBi 10.Chrome 14 supports HyBi 10 protocol although the WebSocket JavaScript API changes mentioned above are still on the way Firefox 7 is also planne d to support HyBi 10.Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3 0 License and code samples are licensed under the Apache 2 0 License For details, see our Site Policies Java is a registered trademark of Oracle and or its affiliates. 28, 2017.The latest news on the Chromium blog. Fork our API code samples and other open-source projects. Connect with ChromiumDev on Twitter. Check out the Web Developer Relations team s videos. Attend a developer event and get hacking. Contribute to WebFundamentals. High Performance Browser Networking by Ilya Grigorik. Chapter 17 WebSocket. WebSocket enables bidirectional, message-oriented streaming of text and binary data between client and server It is the closest API to a raw network socket in the browser Except a WebSocket connection is also much more than a network socket, as the browser abstracts all the complexity behind a simple API and provides a number of additional services. Connection negotiation and same-origin policy enforcement. Interoperability with existing infrastructure. Message-oriented communication and efficient message framing. Subprotocol negotiation and extensibility. WebSocket is one of the most versatile and flexible transports available in the browser The simple and min imal API enables us to layer and deliver arbitrary application protocols between client and server anything from simple JSON payloads to custom binary message formats in a streaming fashion, where either side can send data at any time. However, the trade-off with custom protocols is that they are, well, custom The application must account for missing state management, compression, caching, and other services otherwise provided by the browser There are always design constraints and performance trade-offs, and leveraging WebSocket is no exception In short, WebSocket is not a replacement for XHR, or SSE, and for best performance it is critical that we leverage the strengths of each transport. WebSocket is a set of multiple standards the WebSocket API is defined by the W3C, and the WebSocket protocol RFC 6455 and its extensions are defined by the HyBi Working Group IETF. WebSocket API. The WebSocket API provided by the browser is remarkably small and simple Once again, all the low-level detail s of connection management and message processing are taken care of by the browser To initiate a new connection, we need the URL of a WebSocket resource and a few application callbacks. Open a new secure WebSocket connection wss. Optional callback, invoked if a connection error has occurred. Optional callback, invoked when the connection is terminated. Optional callback, invoked when a WebSocket connection is established. Client-initiated message to the server. A callback function invoked for each new message from the server. Invoke binary or text processing logic for the received message. The API speaks for itself In fact, it should look very similar to the EventSource API we saw in the preceding chapter This is intentional, as WebSocket offers similar and extended functionality Having said that, there are a number of important differences as well Let s take a look at them one by one. WebSocket protocol has undergone a number of revisions, implementation rollbacks, and security investigations However, the good news is that the latest version v13 defined by RFC6455 is now supported by all modern browsers The only notable omission is the Android browser For the latest status, see. Similar to the SSE polyfill strategy Emulating EventSource with Custom JavaScript , the WebSocket browser API can be emulated via an optional JavaScript library However, the hard part with emulating WebSockets is not the API, but the transport As a result, the choice of the polyfill library and its fallback transport XHR polling, EventSource, iframe polling, etc will have significant impact on the performance of an emulated WebSocket session. To simplify cross-browser deployment, popular libraries such as SockJS provide an implementation of WebSocket-like object in the browser but also go one step further by providing a custom server that implements support for WebSocket and a variety of alternative transports The combination of a custom server and client is what enables seamless fallback the performa nce suffers, but the application API remains the same. Other libraries, such as go even further by implementing additional features, such as heartbeats, timeouts, support for automatic reconnects, and more, in addition to a multitransport fallback functionality. When considering a polyfill library or a real-time framework, such as pay close attention to the underlying implementation and configuration of the client and server always leverage the native WebSocket interface for best performance, and ensure that fallback transports meet your performance goals. WS and WSS URL Schemes. The WebSocket resource URL uses its own custom scheme ws for plain-text communication e g , and wss when an encrypted channel TCP TLS is required Why the custom scheme, instead of the familiar. The primary use case for the WebSocket protocol is to provide an optimized, bi-directional communication channel between applications running in the browser and the server However, the WebSocket wire protocol can be used out side the browser and could be negotiated via a exchange As a result, the HyBi Working Group chose to adopt a custom URL scheme. Despite the negotiation option enabled by the custom scheme, in practice there are no existing standards for alternative handshake mechanisms for establishing a WebSocket session. Receiving Text and Binary Data. WebSocket communication consists of messages and application code and does not need to worry about buffering, parsing, and reconstructing received data For example, if the server sends a 1 MB payload, the application s onmessage callback will be called only when the entire message is available on the client. Further, the WebSocket protocol makes no assumptions and places no constraints on the application payload both text and binary data are fair game Internally, the protocol tracks only two pieces of information about the message the length of payload as a variable-length field and the type of payload to distinguish UTF-8 from binary transfers. When a new message is received by the browser, it is automatically converted to a DOMString object for text-based data, or a Blob object for binary data, and then passed directly to the application The only other option, which acts as performance hint and optimization for the client, is to tell the browser to convert the received binary data to an ArrayBuffer instead of Blob. Force an ArrayBuffer conversion when a binary message is received. User agents can use this as a hint for how to handle incoming binary data if the attribute is set to blob , it is safe to spool it to disk, and if it is set to arraybuffer , it is likely more efficient to keep the data in memory Naturally, user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in memory or not. The WebSocket API W3C Candidate Recommendation. A Blob object represents a file-like object of immutable, raw data If you do not need to modify the data and do not need to slice it into smaller chunks, then it is the optimal format e g you can pass the entire Blob object to an image tag see the example in Downloading Data with XHR On the other hand, if you need to perform additional processing on the binary data, then ArrayBuffer is likely the better fit. Decoding Binary Data with JavaScript. An ArrayBuffer is a generic, fixed-length binary data buffer However, an ArrayBuffer can be used to create one or more ArrayBufferView objects, each of which can present the contents of the buffer in a specific format For example, let s assume we have the following C-like binary data structure. Given an ArrayBuffer object of this type, we can create multiple views into the same buffer, each with its own offset and data type. Each view takes the parent buffer, starting byte offset, and number of element s to process the offset is calculated based on the size of the preceding fields As a result, ArrayBuffer and WebSocket give our applications all the necessary tools to stream and process binary data within the browser. Sending Text and Binary Data. Once a WebSocket connection is established, the client can send and receive UTF-8 and binary messages at will WebSocket offers a bidirectional communication channel, which allows message delivery in both directions over the same TCP connection. Send a UTF-8 encoded text message. Send a UTF-8 encoded JSON payload. Send the ArrayBuffer contents as binary payload. Send the ArrayBufferView contents as binary payload. Send the Blob contents as binary payload. The WebSocket API accepts a DOMString object, which is encoded as UTF-8 on the wire, or one of ArrayBuffer, ArrayBufferView, or Blob objects for binary transfers However, note that the latter binary options are simply an API convenience on the wire, a WebSocket frame is either marked as binary or te xt via a single bit Hence, if the application, or the server, need other content-type information about the payload, then they must use an additional mechanism to communicate this data. The send method is asynchronous the provided data is queued by the client, and the function returns immediately As a result, especially when transferring large payloads, do not mistake the fast return for a signal that the data has been sent To monitor the amount of data queued by the browser, the application can query the bufferedAmount attribute on the socket. Subscribe to application updates e g game state changes. Check the amount of buffered data on the client. Send the next update if the buffer is empty. The preceding example attempts to send application updates to the server, but only if the previous messages have been drained from the client s buffer Why bother with such checks All WebSocket messages are delivered in the exact order in which they are queued by the client As a result, a large backlog of queued messages, or even a single large message, will delay delivery of messages queued behind it head-of-line blocking. To work around this problem, the application can split large messages into smaller chunks, monitor the bufferedAmount value carefully to avoid head-of-line blocking, and even implement its own priority queue for pending messages instead of blindly queuing them all on the socket. Many applications generate multiple classes of messages high-priority updates, such as control traffic, and low-priority updates, such as background transfers To optimize delivery, the application should pay close attention to how and when each type of message is queued on the socket. Subprotocol Negotiation. WebSocket protocol makes no assumptions about the format of each message a single bit tracks whether the message contains text or binary data, such that it can be efficiently decoded by the client and server, but otherwise the message contents are opaque. Further, unlike or XHR requests, w hich communicate additional metadata via headers of each request and response, there is no such equivalent mechanism for a WebSocket message As a result, if additional metadata about the message is required, then the client and server must agree to implement their own subprotocol to communicate this data. The client and server can agree on a fixed message format upfront e g all communication will be done via JSON-encoded messages or a custom binary format, and necessary message metadata will be part of the encoded structure. If the client and server need to transfer different data types, then they can agree on a consistent message header, which can be used to communicate the instructions to decode the remainder of the payload. A mix of text and binary messages can be used to communicate the payload and metadata information e g a text message can communicate an equivalent of headers, followed by a binary message with the application payload. This list is just a small sample of possible stra tegies The flexibility and low overhead of a WebSocket message come at the cost of extra application logic However, message serialization and management of metadata are only part of the problem Once we determine the serialization format for our messages, how do we ensure that both client and server understand each other, and how do we keep them in sync. Thankfully, WebSocket provides a simple and convenient subprotocol negotiation API to address the second problem The client can advertise which protocols it supports to the server as part of its initial connection handshake. Array of subprotocols to advertise during WebSocket handshake. Check the subprotocol chosen by the server. As the preceding example illustrates, the WebSocket constructor accepts an optional array of subprotocol names, which allows the client to advertise the list of protocols it understands or is willing to use for this connection The specified list is sent to the server, and the server is allowed to pick one of the pr otocols advertised by the client. If the subprotocol negotiation is successful, then the onopen callback is fired on the client, and the application can query the protocol attribute on the WebSocket object to determine the chosen protocol On the other hand, if the server does not support any of the client protocols advertised by the client, then the WebSocket handshake is incomplete the onerror callback is invoked, and the connection is terminated. The subprotocol names are defined by the application and are sent as specified to the server during the initial handshake Other then that, the specified subprotocol has no effect on the core WebSocket API. WebSocket Protocol. The WebSocket wire protocol RFC 6455 developed by the HyBi Working Group consists of two high-level components the opening handshake used to negotiate the parameters of the connection and a binary message framing mechanism to allow for low overhead, message-based delivery of both text and binary data. The WebSocket Protocol attempts to address the goals of existing bidirectional technologies in the context of the existing infrastructure as such, it is designed to work over ports 80 and 443 However, the design does not limit WebSocket to and future implementations could use a simpler handshake over a dedicated port without reinventing the entire protocol. WebSocket Protocol RFC 6455.WebSocket protocol is a fully functional, standalone protocol that can be used outside the browser Having said that, its primary application is as a bidirectional transport for browser-based applications. Binary Framing Layer. Client and server WebSocket applications communicate via a message-oriented API the sender provides an arbitrary UTF-8 or binary payload, and the receiver is notified of its delivery when the entire message is available To enable this, WebSocket uses a custom binary framing format Figure 17-1 , which splits each application message into one or more frames transports them to the destination, reassembles them, and finally notifies the receiver once the entire message has been received. Figure 17-1 WebSocket frame 2 14 bytes payload. Frame The smallest unit of communication, each containing a variable-length frame header and a payload that may carry all or part of the application message Message A complete sequence of frames that map to a log ical application message. The decision to fragment an application message into multiple frames is made by the underlying implementation of the client and server framing code Hence, the applications remain blissfully unaware of the individual WebSocket frames or how the framing is performed Having said that, it is still useful to understand the highlights of how each WebSocket frame is represented on the wire. The first bit of each frame FIN indicates whether the frame is a final fragment of a message A message may consist of just a single frame. The opcode 4 bits indicates type of transferred frame text 1 or binary 2 for transferring application data or a control frame such as connection close 8 , ping 9 , and pong 10 for connection liveness checks. The mask bit indicates whether the payload is masked for messages sent from the client to the server only. Payload length is represented as a variable-length field. If 0 125, then that is the payload length. If 126, then the following 2 bytes repr esent a 16-bit unsigned integer indicating the frame length. If 127, then the following 8 bytes represent a 64-bit unsigned integer indicating the frame length. Masking key contains a 32-bit value used to mask the payload. Payload contains the application data and custom extension data if the client and server negotiated an extension when the connection was established. The payload of all client-initiated frames is masked using the value specified in the frame header this prevents malicious scripts executing on the client from performing a cache poisoning attack against intermediaries that may not understand the WebSocket protocol For full details of this attack, refer to Talking to Yourself for Fun and Prot presented at W2SP 2011.As a result, each server-sent WebSocket frame incurs 2 10 bytes of framing overhead The client must also send a masking key, which adds an extra 4 bytes to the header, resulting in 6 14 bytes over overhead No other metadata, such as header fields or other informa tion about the payload, is available all WebSocket communication is performed by exchanging frames that treat the payload as an opaque blob of application data. WebSocket Multiplexing and Head-of-Line Blocking. WebSocket is susceptible to head-of-line blocking messages can be split into one or more frames, but frames from different messages can t be interleaved, as there is no equivalent to a stream ID found in the 2 0 framing mechanism see Streams, Messages, and Frames. As a result, a large message, even when split into multiple WebSocket frames, will block the delivery of frames associated with other messages If your application is delivering latency-sensitive data, be careful about the payload size of each message and consider splitting large messages into multiple application messages. The lack of multiplexing in core WebSocket specification also means that each WebSocket connection requires a dedicated TCP connection, which may become a potential problem for 1 x deployments due to a r estricted number of connections per origin maintained by the browser see Exhausting Client and Server Resources. On the bright side, the new Multiplexing Extension for WebSockets developed by the HyBi Working Group addresses the latter limitation. With this extension, one TCP connection can provide multiple virtual WebSocket connections by encapsulating frames tagged with a channel ID The multiplexing extension maintains separate logical channels, each of which provides fully the logical equivalent of an independent WebSocket connection, including separate handshake headers. WebSocket Multiplexing Draft 10.With this extension in place, multiple WebSocket connections channels can be multiplexed over the same TCP connection However, each individual channel is still susceptible to head-of-line blocking Hence, one potential workaround is to use different channels, or dedicated TCP connections, to multiplex multiple messages in parallel. Finally, note that the preceding extension is necessary only for 1 x connections While no official specification is yet available for transporting WebSocket frames with 2 0, doing so would be much easier 2 0 has built-in stream multiplexing, and multiple WebSocket connections could be transported within a single session by encapsulating WebSocket frames within the 2 0 framing mechanism. Protocol Extensions. WebSocket specification allows for protocol extensions the wire format and the semantics of the WebSocket protocol can be extended with new opcodes and data fields While somewhat unusual, this is a very powerful feature, as it allows the client and server to implement additional functionality on top of the base WebSocket framing layer without requiring any intervention or cooperation from the application code. What are some examples of WebSocket protocol extensions The HyBi Working Group, which is responsible for the development of the WebSocket specification, lists two official extensions in development. A Multiplexing Extension for WebSockets This extension provides a way for separate logical WebSocket connections to share an underlying transport connection Compression Extensions for WebSocket A framework for creating WebSocket extensions that add compression functionality to the WebSocket Protocol. As we noted earlier, each WebSocket connection requires a dedicated TCP connection, which is inefficient Multiplexing extension addresses this problem by extending each WebSocket frame with an additional channel ID to allow multiple virtual WebSocket channels to share a single TCP connection. Similarly, the base WebSocket specification provides no mechanism or provisions for compression of transferred data each frame carries payload data as provided by the application As a result, while this may not be a problem for optimized binary data structures, this can result in high byte transfer overhead unless the application implements its own data compression and decompression logic In effect, com pression extension enables an equivalent of transfer-encoding negotiation provided by. To enable one or more extensions, the client must advertise them in the initial Upgrade handshake, and the server must select and acknowledge the extensions that will be used for the lifetime of the negotiated connection For a hands-on example, let s now take a closer look at the Upgrade sequence. WebSocket Multiplexing and Compression in the Wild. As of mid-2013, WebSocket multiplexing is not yet supported by any popular browser Similarly, there is limited support for compression Google Chrome and the latest WebKit browsers may advertise an x-webkit-deflate-frame extension to the server However, deflate-frame is based on an outdated revision of the standard and will be deprecated in the future. As the name implies, per-frame compresses the payload contents on a frame-by-frame basis, which is suboptimal for large messages that may be split between multiple frames As a result, latest revisions of the comp ression extension have switched to per-message compression that s the good news The bad news is per-message compression is still experimental and is not yet available in any popular browser. As a result, the application should pay close attention to the content-type of transferred data and apply its own compression where applicable That is, at least until native WebSocket compression support is available widely across all the popular browsers This is especially important for mobile applications, where each unnecessary byte carries high costs to the user. Upgrade Negotiation. The WebSocket protocol delivers a lot of powerful features message-oriented communication, its own binary framing layer, subprotocol negotiation, optional protocol extensions, and more As a result, before any messages can be exchanged, the client and server must negotiate the appropriate parameters to establish the connection. Leveraging to perform the handshake offers several advantages First, it makes WebSockets compatible with existing infrastructure WebSocket servers can run on port 80 and 443, which are frequently the only open ports for the client Second, it allows us to reuse and extend the Upgrade flow with custom WebSocket headers to perform the negotiation. Sec-WebSocket-Version Sent by the client to indicate version 13 for RFC6455 of the WebSocket protocol it wants to use If the server does not support the client version, then it must reply with a list of supported versions Sec-WebSocket-Key An auto-generated key sent by the client, which acts as a challeng e to the server to prove that the server supports the requested version of the protocol Sec-WebSocket-Accept Server response that contains signed value of Sec-WebSocket-Key, proving that it understands the requested protocol version Sec-WebSocket-Protocol Used to negotiate the application subprotocol client advertises the list of supported protocols server must reply with a single protocol name Sec-WebSocket-Extensions Used to negotiate WebSocket extensions to be used for this connection client advertises supported extensions, and the server confirms one or more extensions by returning the same header. With that, we now have all the necessary pieces to perform an Upgrade and negotiate a new WebSocket connection between the client and server. Request to perform an upgrade to the WebSocket protocol. WebSocket protocol version used by the client. Auto-generated key to verify server protocol support. Optional list of subprotocols specified by the application. Optional list of protocol extensions supported by the client. Just like any other client-initiated connection in the browser, WebSocket requests are subject to the same-origin policy the browser automatically appends the Origin header to the upgrade handshake, and the remote server can use CORS to accept or deny the cross origin request see Cross-Origin Resource Sharing CORS To complete the handshake, the server must return a successful Switching Protocols response and confirm the selected options advertised by the client.101 response code confirming WebSocket upgrade. CORS header indicating opt-in for cross-origin connection. Signed Key value proving protocol support. Application subprotocol selected by the server. List of WebSocket extensions selected by the server. All RFC6455-compatible WebSocket servers use the same algorithm to compute the answer to the client challenge the contents of the Sec-WebSocket-Key are concatenated with a unique GUID string defined in the standard, a SHA1 hash is computed, and the resulting stri ng is base-64 encoded and sent back to the client. At a minimum, a successful WebSocket handshake must contain the protocol version and an auto-generated challenge value sent by the client, followed by a 101 response code Switching Protocols from the server with a hashed challenge-response to confirm the selected protocol version. Client must send Sec-WebSocket-Version and Sec-WebSocket-Key. Server must confirm the protocol by returning Sec-WebSocket-Accept. Client may send a list of application subprotocols via Sec-WebSocket-Protocol. Server must select one of the advertised subprotocols and return it via Sec-WebSocket-Protocol If the server does not support any, then the connection is aborted. Client may send a list of protocol extensions in Sec-WebSocket-Extensions. Server may confirm one or more selected extensions via Sec-WebSocket-Extensions If no extensions are provided, then the connection proceeds without them. Finally, once the preceding handshake is complete, and if the handshake is successful, the connection can now be used as a two-way communication channel for exchanging WebSocket messages From here on, there is no other explicit communication between the client and server, and the WebSocket protocol takes over. Proxies, Intermediaries, and WebSockets. In practice, for security and policy reasons, many users have a restricted set of open ports specifically port 80 and port 443 As a result, WebSocket negotiation is performed via the Upgrade flow to ensure the best compatibility with existing network policies and infrastructure. However, as we noted earlier in Proxies, Intermediaries, TLS, and New Protocols on the Web many existing intermediaries may not understand the new WebSocket protocol, which can lead to a variety of failure cases blind connection upgrades, unintended buffering of WebSocket frames, content modification without understanding of the protocol, misclassification of WebSocket traffic as compromised connections, and so on. The WebSocket Key and Acce pt handshake addresses some of these problems it is a security policy against servers and intermediaries that may blindly upgrade the connection without actually understanding the WebSocket protocol However, while this precaution addresses some deployment issues with explicit proxies, it is nonetheless insufficient for transparent proxies, which may analyze and modify the data on the wire without notice. The workaround Establish a secure end-to-end tunnel i e use WSS By negotiating a TLS session prior to performing the Upgrade handshake, the client and server establish an encrypted tunnel, which resolves all of the previously listed concerns This is especially true for mobile clients, whose traffic often passes through a variety of proxy services that may not play well with WebSocket. WebSocket Use Cases and Performance. WebSocket API provides a simple interface for bidirectional, message-oriented streaming of text and binary data between client and server pass in a WebSocket URL to the c onstructor, set up a few JavaScript callback functions, and we are up and running the rest is handled by the browser Add to that the WebSocket protocol, which offers binary framing, extensibility, and subprotocol negotiation, and WebSocket becomes a perfect fit for delivering custom application protocols in the browser. However, just as with any discussion on performance, while the implementation complexity of the WebSocket protocol is hidden from the application, it nonetheless has important performance implications for how and when WebSocket should be used WebSocket is not a replacement for XHR or SSE, and for best performance it is critical that we leverage the strengths of each transport. Refer to XHR Use Cases and Performance and SSE Use Cases and Performance for a review of the performance characteristics of each transport. Request and Response Streaming. WebSocket is the only transport that allows bidirectional communication over the same TCP connection Figure 17-2 the client and se rver can exchange messages at will As a result, WebSocket provides low latency delivery of text and binary application data in both directions. Figure 17-2 Communication flow of XHR, SSE, and WebSocket. XHR is optimized for transactional request-response communication the client sends the full, well-formed request to the server, and the server responds with a full response There is no support for request streaming, and until the Streams API is available, no reliable cross-browser response streaming API. SSE enables efficient, low-latency server-to-client streaming of text-based data the client initiates the SSE connection, and the server uses the event source protocol to stream updates to the client The client can t send any data to the server after the initial handshake. Propagation and Queuing Latency. Switching transports from XHR to SSE or WebSocket does not decrease the roundtrip between client and server Regardless of the transport, the propagation latency of the data packets is the s ame However, aside from propagation latency, there is also the queuing latency the time the message has to wait on the client or server before it can be routed to the other party. In the case of XHR polling, the queuing latency is a function of the client polling interval the message may be available on the server, but it cannot be sent until the next client XHR request see Modeling Performance of XHR Polling By contrast, both SSE and WebSocket use a persistent connection, which allows the server to dispatch the message and client, in the case of WebSocket , the moment it becomes available. As a result, low-latency delivery for SSE and WebSocket is specifically referring to the elimination of message queuing latency We have not yet figured out how to make WebSocket data packets travel faster than the speed of light. Message Overhead. Once a WebSocket connection is established, the client and server exchange data via the WebSocket protocol application messages are split into one or more fra mes, each of which adds from 2 to 14 bytes of overhead Further, because the framing is done via a custom binary format, both UTF-8 and binary application data can be efficiently encoded via the same mechanism How does that compare with XHR and SSE. SSE adds as little as 5 bytes per message but is restricted to UTF-8 content only see Event Stream Protocol. 1 x requests XHR or otherwise will carry an additional 500 800 bytes of metadata, plus cookies see Measuring and Controlling Protocol Overhead. 2 0 compresses the metadata, which significantly reduces the overhead see Header Compression In fact, if the headers do not change between requests, the overhead can be as low as 8 bytes. Keep in mind that these overhead numbers do not include the overhead of IP, TCP, and TLS framing, which add 60 100 bytes of combined overhead per message, regardless of the application protocol see TLS Record Size. Data Efficiency and Compression. Every XHR request can negotiate the optimal transfer encoding format e g gzip for text-based data , via regular negotiation Similarly, because SSE is restricted to UTF-8 only transfers, the event stream data can be efficiently compressed by applying gzip across the entire session. With WebSocket, the situation is more complex WebSocket can transfer both text and binary data, and as a result it doesn t make sense to compress the entire session The binary payloads may be compressed already As a result, WebSocket must implement its own compression mechanism and sel ectively apply it to each message. The good news is the HyBi working group is developing the per-message compression extension for the WebSocket protocol However, it is not yet available in any of the browsers As a result, unless the application implements its own compression logic by carefully optimizing its binary payloads see Decoding Binary Data with JavaScript and implementing its own compression logic for text-based messages, it may incur high byte overhead on the transferred data. Chrome and some WebKit-based browsers support an older revision per-frame compression of the compression extension to the WebSocket protocol see WebSocket Multiplexing and Compression in the Wild. Custom Application Protocols. The browser is optimized for data transfers it understands the protocol, and it provides a wide array of services, such as authentication, caching, compression, and much more As a result, XHR requests inherit all of this functionality for free. By contrast, streaming allows us to deli ver custom protocols between client and server, but at the cost of bypassing many of the services provided by the browser the initial handshake may be able to perform some negotiation of the parameters of the connection, but once the session is established, all further data streamed between the client and server is opaque to the browser As a result, the flexibility of delivering a custom protocol also has its downsides, and the application may have to implement its own logic to fill in the missing gaps caching, state management, delivery of message metadata, and so on. The initial Upgrade handshake does allow the server to leverage the existing cookie mechanism to validate the user If the validation fails, the server can decline the WebSocket upgrade. Leveraging Browser and Intermediary Caches. Using regular has significant advantages Ask yourself a simple question would the client benefit from caching the received data Or could an intermediary optimize the delivery of the asset if it cou ld cache it. For example, WebSocket supports binary transfers, which allows the application to stream arbitrary image formats with no overhead nice win However, the fact that the image is delivered within a custom protocol means that it won t be cached by the browser cache, or any intermediary e g a CDN As a result, you may incur unnecessary transfers to the client and much higher traffic to the origin servers The same logic applies to all other data formats video, text, and so on. As a result, make sure you choose the right transport for the job A simple but effective strategy to address these concerns could be to use the WebSocket session to deliver non-cacheable data, such as real-time updates and application control messages, which can trigger XHR requests to fetch other assets via the protocol. Deploying WebSocket Infrastructure. is optimized for short and bursty transfers As a result, many of the servers, proxies, and other intermediaries are often configured to aggressively timeout idle connections, which, of course, is exactly what we don t want to see for long-lived WebSocket sessions To address this, there are three pieces to consider. Routers, load-balancers, and proxies within own network. Transparent and explicit proxies in external network e g ISP and carrier proxies. Routers, firewalls, and proxies within the client s network. We have no control over the policy of the client s network In fact, some networks may block WebSocket traffic entirely, which is why you may need a fallback strategy Similarly, we don t have control over the proxies on the external network However, this is where TLS may help By tunneling over a secure end-to-end connection, WebSocket traffic can bypass all the intermediate proxies. Using TLS does not prevent the intermediary from timing out an idle TCP connection However, in practice , it significantly increases the success rate of negotiating the WebSocket session and often also helps to extend the connection timeout intervals. Finally, there is the infrastructure that we deploy and manage ourselves, which also often requires attention and tuning As easy as it is to blame the client or external networks, all too often the problem is close to home Each load-balancer, router, proxy, and web server in the serving path must be tuned to allow long-lived connections. For example, Nginx 1 3 13 can proxy WebSocket traffic, but defaults to aggressive 60-second timeouts To increase the limit, we must explicitly define the longer timeouts. Set 60-minute timeout between reads. Set 60-minute timeout between writes. Similarly, it is not uncommon to have a load balancer, such as HAProxy, in front of one or more Nginx servers Not surprisingly, we need to apply similar explicit configuration here as well e g for HAProxy.60-minute inactivity timeout for tunnels. The gotcha with the prece ding example is the extra tunnel timeout In HAProxy the connect client and server timeouts are applied only to the initial Upgrade handshake, but once the upgrade is complete, the timeout is controlled by the tunnel value. Nginx and HAProxy are just two of hundreds of different servers, proxies, and load balancers running in our data centers We can t enumerate all the configuration possibilities in these pages The previous examples are just an illustration that most infrastructure requires custom configuration to handle long-lived sessions Hence, before implementing application keepalives, double-check your infrastructure first. Long-lived and idle sessions occupy memory and socket resources on all the intermediate servers Hence, short timeouts are often justified as a security, resource, and operational precaution Deploying WebSocket, SSE, and 2 0, each of which relies on long-lived sessions, brings its own class of new operational challenges. Performance Checklist. Deploying a high-perfo rmance WebSocket service requires careful tuning and consideration, both on the client and on the server A short list of criteria to put on the agenda. Use secure WebSocket WSS over TLS for reliable deployments. Pay close attention to polyfill performance if necessary. Leverage subprotocol negotiation to determine the application protocol. Optimize binary payloads to minimize transfer size. Consider compressing UTF-8 content to minimize transfer size. Set the right binary type for received binary payloads. Monitor the amount of buffered data on the client. Split large application messages to avoid head-of-line blocking. Leverage other transports where applicable. Last, but definitely not least, optimize for mobile Real-time push can be a costly performance anti-pattern on mobile handsets, where battery life is always at a premium That s not to say that WebSocket should not be used on mobile To the contrary, it can be a highly efficient transport, but make sure to account for its requirements. Wit h Safari, you learn the way you learn best Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more. No credit card required. Websockets 101.written on Monday, September 24, 2012.Out of curiosity I taught the Fireteam presence server websockets as a protocol in addition to the proprietary protocol it speaks out of the box I don t really have a usecase for websocket per-se with the server, but I thought it might make it more useful for customers that want to use the event based parts of the API with HTML5 games This post focuses on implementing websockets on the server, not so much about how you would use them from the client and basically collects all thing I wish I would have known before. What are Websockets. So let s start with that part first What are websockets and why would you use websockets Basically only if you want to have a bidirectional communication between an actual web browser and some server Websocket is not necessarily a good protocol if neither of the endpoints is an actual browser Websockets suffer a lot under the restrictions and implementation details that were forced upon the protocol to make it work with existing infrastructure. Websockets in the current iteration as specified by RFC 6455 do a bunch of things differently to what a raw TCP connections does The name websocket gives the impression that it s a traditional socket In practice it combines the parts of UDP and TCP it s message based like UDP, but it s reliable like TCP So assuming you know what TCP is, here is what websocket adds on top of that. it upgrades from 1 1 through a system previously defined as part of the specification upgrade header. it sends the origin domain in the upgrade so that connections can be restricted to prevent CSRF attacks This works similar to CORS for. Through the handshake it becomes feasible to proxy the connection without losing information a proxy could inject an X-Real-IP or X-Forwarded-For header. It sends mes sages Each message can also carry control information and is wrapped in a frame. Messages sent from the client to the server are obfuscated with a basic transmission mask of 4 bytes which is sent within each websocket package Messages can be of utf-8 text type or binary nature. It adds an agreed way for the two peers to signal that the connection is about to be terminated that does not rely on the underlying TCP connection. Builtin heartbeating support That s actually pretty nifty because the application code in the browser does not have to deal with keeping the connection alive and can just assume that either the server or the browser will make sure that they exchange ping pongs. When to use them. Websockets make you sad There, I said it What started out as a really small simple thing ended up as an abomination of what feels like needles complexity Now the complexity comes for a reason The protocol went through many iterations and basically had to be changed multiple times because of unfor eseen security problems that came up with misbehaving proxies The protocol I created for the internal communication of our server is upgrading from just like websockets do, but without the secure parts And here is why it does not matter. Everybody knows about proxies We have proxies that do load balancing on the application side, we have proxies that do SSL offloading, we have proxies for all kinds of things Unfortunately outside our internal infrastructure everyone of us also has to deal with proxies in corporate networks, and worse, on mobile network connections The amount of shitty middleware installed all around the world is just staggering And this pretty much has shown me that the only way you can do anything useful these days is by putting TLS on top of everything and just force people to stop with their shenanigans On O2 s mobile networks you cannot use websockets unless they are encrypted You cannot get websocket connections through Amazon s ELB Their load balancer Heck, you ca n t even get PATCH as an method through the ELB. Everything that Fireteam will be doing will most likely always be behind an encrypted connection It guarantees me that nothing can do funny things with the data I m sending around And as a positive side effect I don t have to mask my communication like websocket does because I know the software stack on my side until it hits the internet The communication gets encrypted and I know nobody is going to change my data on the way to the client. In fact, I would also recommend to always use websockets through TLS Even if you don t care about the security side of things you will still benefit from the fact that your websocket connections succeed in many more cases Not encrypting your connection is definitely something you will regret sooner or later. The Handshake. Alright After this fairly long disclaimer you re still there, which probably means you still want to do websockets Fair enough Now let s start with the basics, the handshake This is wher e everything starts It upgrades your connection from to something else For the internal protocol we recommend to customers we upgrade our connection basically to a raw TCP connection Websockets are not an upgrade to TCP, it s an upgrade to a message based communication. To begin why would you upgrade from instead of directly starting with TCP as a protocol The reasons for why Fireteam s protocol starts with not all that different from why websockets upgrade from. Websockets upgrade from because it was believed that people would develop servers that serve both websocket connections as well as ones I don t believe for a second that this will be what people do at the end of the day however A server that handles stateless requests to answer with a reply has a very different behavior than a server that keeps TCP connections open However the advantage is that websockets use the same ports as and do and that is a huge win It s a win because these are privileged ports 1024 and they are tradition ally handled differently than non privileged ports For instance on a linux system only root can open such ports Even more important ELB only lets you open a handful of these privileged ports 25, 80 and 443 to be exact Since ELB also does socket level load balancing you can still do websockets on Amazon, just not through their local balancer. We re handling our persistent presence protocol very differently than our webservice but we still benefit from the upgrade in some edge cases That s mainly where we have to tunnel our communication through a library because arbitrary socket connections are not possible for security or scalability reasons If you have ever used Google Appengine or early Windows Phone you will have noticed that connections are possible where regular socket connections are not. You will also see that many corporate networks only allow certain ports outgoing The fact that websockets use the same port as make this much more interesting If anyone has ever used the flash soc ket policy system will know that pain Currently it s entirely impossible to use flash sockets behind Amazon s ELB because the Flash VM will attempt to connect to port 843 to get authorization information That s a port you can t open on the ELB So the idea of starting with is pretty solid. always supported upgrades, but unfortunately many proxies seem to have ignored that part of the specification The main reason for that probably is that until websockets came around nobody was actually using the Upgrade flag There was an SSL upgrade RFC that used the same mechanism but I don t think anyone is using that. Alright So what does the handshake look like The upgrade is initiated by the client, not by the server The way Fireteam upgrades the connection is by following the old SSL RFC and looks like this. The server then replies by upgrading. If the upgrade header was missing, the server instead answers with 426 Upgrade Required. What s interesting about this is that the upgrade require status code is defined, but it does not show up in the RFC Instead if does come from that SSL RFC. Websockets upgrade very similar, but they are using 400 Bad Request to signal a missing upgrade They also transmit a special key with the upgrade request which the server has to process and send back Th is is done so that a websocket connection cannot be established with an endpoint that is not aware of websockets Here is what the handshake looks like for the client. The websocket key here are random bytes The server takes these bytes and appends the special string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 to it, then creates the SHA1 hash from it and base64 encodes the result the bytes, not the hexadecimal representation The magic string looks like a UUID and also is one, but that s completely irrelevant because the exact string needs to be used A lowercase representation or braces around the string would obviously fail That value is then put into the Sec-WebSocket-Accept header When the server has computed the value it can send an upgrade response back. The handshake can also include a protocol request and the websocket version information but you can t include arbitrary other headers If you compare the websocket upgrade with our own upgrade you will notice that we can t transmit the autho rization information There are two ways around that You can either transmit the authorization information as the first request or put it into the URL as query parameter. Also notice that the Sec-WebSocket-Accept header brings it s own grammar for the value Normally you would expect you can quote the value but the specification specifically requires a base64 value there. Websocket URLs. Alright As if websockets were not painful enough as they are, someone had the amazing idea to also introduce a new URL scheme Two in fact ws and wss Sounds like a tiny change from to but unfortunately that s not the case URLs have scheme specific grammar For instance FTP URLs can have authorization information in the netloc part ftp username server whereas can t mailto URLs don t have the leading slashes etc Websocket URLs are special in that they do not support anchors foo Now why would that matter It matters because whoever created the URL parsing module in Python also decided that they should stick as cl osely as possible to the strict standard that you cannot throw arbitrary URLs at the module For instance if you would try to parse websocket URLs you quickly realize that the results are just wrong. The reason why websockets have a separate URL is beyond me I suspect it stems from the fact that the RFC hints towards eventually dropping the upgrade from so the URL would not make much sense In any case it s just a very annoying example of where we now have to things now that were previously unnecessary. Also since it s a different protocol, protocol relative links will obviously not work You will have to switch between wss and ws by hand. Otherwise the same rules as for style URLs apply Namely that ws is unencrypted and has port 80 as default port and wss requires TLS encryption and port 443 as default. Authorization and IPs. Before we dive further into websockets let me throw yet another problem at you Since proxying is a word that comes up with websockets so very often we should probably ta lk about how proxies work there in the original RFC does not really talk much about TCP and IP addresses don t show up in there either However it has become clear over the last couple of years that there is a lot of value behind knowing which IP address connects to your server Traditionally this is doing by looking at the IP address that is stored in the individual IP packets Unfortunately this falls short the moment you start proxying through another server. There are two headers that have become popular to remedy that situation The first one is X-Forwarded-For which can contain one or multiple IPs of servers that took part in the request Each proxy server would add the remote address of the request to the header So if you have a user agent at 192 168 0 100 connect to 192 168 0 200 which acts as a proxy for 192 168 0 201 you end up with an X-Forwarded-For of 192 168 0 100 Bring in yet another proxy server that one would append it s own IP address to that list. Now there has to be a limi t to this Usually what you do is you configure the first server to reject any already set X-Forwarded-For headers or users can just use a browser extension or a proxy to inject a forged value in there And people do that I remember that people did exactly that to get American streaming content available in Europe by just injecting an American IP into that header. With websockets it s worse Odds are that your frontend proxy is doing TCP level proxying If it would be doing level load balancing and it would understand the Upgrade header it you could make it inject an X-Forwarded-For header and then read that on the server However Amazon s ELB as mentioned only works with websockets if you set it to TCP level proxying for instance And with that you lose your remote address Maybe not a problem for you, it definitely is a problem for us Now I know that protocols exists to inform a peer about the IP address on the other side of a proxy connection, but ELB does not speak it so it s a rather unin teresting thing for me. The way our server works is pretty similar to how the juggernaut server used to work You connect to a presence server that holds your socket connection open and acts as a central hub that uses other means to communicate with backend services We have a pretty lightweight server and we don t want to make it too complicated to authorize requests against it Namely we don t want to implement OAuth a second time for that server when we already use it for the strictly request response based webservice infrastructure. The trick we use for that is that we let a user authorize against the webservice infrastructure through OAuth and then call an endpoint that gives you a ticket that is valid for a few seconds That ticket is stored in redis It contains your account ID and a few important internal attributes, but we also store the IP on it which you used at the time the ticket was generated. With that ticket you go to the presence server and redeem it The presence server only n eeds to connect to redis and check if such a ticket exist and delete it Since we already use redis anyways in that server it s a pretty simple undertaking We obviously assume here that nobody takes the ticket between IP addresses We can t gurantee that this does not happen but we don t care about the implications either Someone could obviously create the ticket through a VPN and then disable the VPN connection when it s time to connect to the presence server But to be honest I don t care It s as far as I am concerned, no security problem. In theory the spec says you can also use any of the authorization systems basic auth, cookies etc but since you can t customize the headers with the JavaScript API that are being sent with the handshake you are basically very limited to implicit auth or auth through one of the first requests URL based. Now that we know how we can connect to the websocket server, how to upgrade to the websocket protocol and how authorization can be handled without losing the IP address information even if we do TCP level load balancing The next thing you have to know is how websocket transfer works As mentioned earlier websocket is not a stream based protocol like TCP, it s message based What s the difference With TCP you send bytes around and have to make sure for the most part that you can figure out the end of a message Our own protocol makes this very easy because we send full JSON objects around which are self terminating For naive JSON parsers like the one in the Python standard library that cannot parse of a stream we also add a newline at the end and ensure that all newlines in JSON strings are escaped So you can just read to the newline and then hand that line to the JSON parser. Websockets makes this easier because it puts a frame around everything Upside easier to handle from the JavaScript side, downside much harder to handle on the server side because you now need to wrap everything in frames. So let s have a look first how the frames are d efined This is what the RFC provides us with. Good news first as of the websocket version specified by the RFC it s only a header in front of each packet The bad news is that it s a rather complex header and it has the frighting word mask in it Here are the individual parts explained. fin 1 bit indicates if this frame is the final frame that makes up the message Most of the time the message fits into a single frame and this bit will always be set Experiments show that Firefox makes a second frame after 32K however. rsv1 rsv2 rsv3 1 bit each it wouldn t be a proper protocol if it did not include reserved bits As of right now, they are unused. opcode 4 bits the opcode Mainly says what the frame represents The following values are currently in use.0x00 this frame continues the payload from the last.0x01 this frame includes utf-8 text data.

No comments:

Post a Comment