1. 계약
WebSocket은 TCP의 클라이언트와 서버 간의 전체 이중 통신을 기반으로 한 프로토콜입니다. HTML5에서 정의되며 또한 새로운 세대의 WebApps의 기본 사양 중 하나입니다.
초기 Ajax의 한계를 뚫고 키는 실시간이며 서버는 컨텐츠를 클라이언트에게 적극적으로 푸시 할 수 있습니다! 가능한 응용 프로그램에는 다음이 포함됩니다 : 멀티 플레이어 온라인 게임, 라이브 채팅, 실시간 모니터링, 원격 데스크탑, 뉴스 서버 등
나 자신을 위해, 내가 지금 가장 시도하고 싶은 것은 Canvas+WebSocket 조합으로 수행 할 수있는 것입니다.
2. 실현
핸드 셰이크 프로세스는 표준 HTTP 요청이므로 WebSocket 구현을위한 두 가지 옵션이 있습니다. 1) TCP에서 구현; 2) 기존 HTTP 소프트웨어에 대한 구현. 후자의 장점은 기존 HTTP 서버 포트를 공유 할 수 있으며 인증 기능을 다시 구현하고 HTTP 요청을 구문 분석 할 필요가 없다는 것입니다.
이 예에서는 노드의 HTTP 모듈이 사용됩니다. (TCP 버전 및 모든 파일의 첨부 파일 참조)
1. 노드 서버 측 코드 :
var http = require ( 'http'); var url = require ( 'url'); // var mime = require ( 'mime'); var crypto = require ( 'crypto'); var port = 4400; var server = http.createserver (); server.listen (port, function () {console.log (서버는 localhost : ', port); server ('connection ', function (s) {console.log ('on connection ', s);}) Object.keys (req), req.url, req [ 'upgrade']); if (! req.upgrade) {// 비 업그레이드 요청 선택 : 정상적인 웹 페이지를 방해하거나 제공합니다. res.write ( 'WebSocket Server Works!'); } res.end (); return;}; var onupgrade = function (req, sock, head) {// console.log ( 'method :', object.keys (sock)); if (req.headers.upgrade! == 'WebSocket') {console.warn ( '불법 연결'); sock.end (); 반품; } bind_sock_event (양); try {handshake (req, sock, head); } catch (e) {console.error (e); sock.end (); }}; // var wrap = function (data) {var fa = 0x00, fe = 0xff, data.tostring () len = 2+buffer.bytelength (data), buff = new buffer (len); 버프 [0] = fa; buff.write (데이터, 1); 버프 [len-1] = fe; return buff;} // 수신 된 프레임 Unfrap var var unhrap = function (data) {return data.slice (1, data.length-1);} var bind_sock_event = function (sock) {sock .on ( 'data', function (buffer) {var data = dehakrap (buffer); console.log (socket); 송신 ( 'hello html5,'+date.now ()) sock.emit ( 'send', data}). sock.write (랩 (데이터), 'binary'); var get_part = function (key), key.replace (// s/g, empty). if (! scaces) strash {message : 'wrong key :'+key, name : 'handshakeError'} return get_big_endian (part / pacse); 함수 (key1, key2, head) {var sum = get_part (key1) + get_part (key2) + head.tostring ( 'binary'); return crypto.createhash ( 'md5'). update (sum). digest ( 'binary');} var handshake = function (req, sock, head) {var output = [], h = req.headers, br = '/r/n'; // 헤더 output.push ( 'http/1.1 101 Websocket 프로토콜 핸드 셰이크', '업그레이드 : websocket', 'connection : 업그레이드', 'sec-websocket-origin :' + h.origin, 'sec-websocket-location : //' + h.host + req.url, 'sec-websocket-prot Colocol : my-custom-chat-chat-chat-chat-chat-chat-chat-chat-chat-prot'; // body var c = challenge (h [ 'sec-websocket-key1'], h [ 'sec-websocket-key2'], 헤드); output.push (c); sock.write (output.join (br), 'binary');}2. 브라우저 클라이언트 코드 :
<html> <head> <title> Websocket Demo </title> </head> <style type = "text/css"> textarea {width : 400px; 높이 : 150px; display : block; overflow-y : scroll;} #output {width : 600px; 버튼 {padding : .2em 1em;} </style> <link href = "layout.css"rel = "stylesheet"type = "text/css"/> <body> <textArea id = "output"readOnly = "readOnly"> </textArea> <br> <TextArea id = "input"> type = "text/javaScript"> // localHostvar 소켓 = 새로운 WebSocket ( 'ws : //192.168.144.131 : 4400/') socket.onopen = function (e) {log (e.type); socket.send ( 'hello node');} socket.onclose = function (e) {log (e.type);} socket.onmessage = function (e) {log ( 'lecce @'+new date (). tolocaletimestring ()+'/n'+e.data); output.scrolltop = output.scrollheight} socket.onclose = function (e) {log (e.type);} socket.addeventListener ( 'close', function () {log ( 'A ATHER CLOSE EVENT HARLER ..');}, FALSE); // domVar id = function (id) {id); id ( 'output'), input = id ( 'input'), send = id ( 'send'); var log = function (msg) {output.textContent += '>' +msg +'/n'} send.addeventListener ( 'click', function () {socket.send (input.value); </script);3. 세부 사항
HTTP 프로토콜 위의 WebSocket 프로토콜 구현에는 핸드 셰이크와 보내기 데이터의 두 단계 만 있습니다.
1. 악수
핸드 셰이크 과정을 챌린지 응답이라고합니다. 먼저, 클라이언트는 HTTP get request 이름이 이름을 업그레이드하고 서버가 요청을 확인하고 101 응답을 제공하여 프로토콜 업그레이드가 수락되고 핸드 셰이크가 완료되었음을 나타냅니다.
Chrome Inspector가 아름답게하는 악수 정보 :
요청 URL : ws : //192.168.144.131 : 4400/pub/chat? q = me
요청 방법 : 얻습니다
상태 코드 : 101 WebSocket 프로토콜 핸드 셰이크
헤더를 요청합니다
연결 : 업그레이드
호스트 : 192.168.144.131 : 4400
원산지 : http : // localhost : 800
SEC-Websocket-Key1 : P2 G 947T 80 661 JAF2
SEC-WEBSOCKE-KEY2 : Z ZQ ^326 5 9 = 7S1 1 7H4
Sec-Websocket-Protocol :: My-Custom-Chat-Protocol
업그레이드 : WebSocket
(key3) : 7c : 44 : 56 : ca : 1f : 19 : d2 : 0a
응답 헤더
연결 : 업그레이드
SEC-Websocket-Location : WS : //192.168.144.131 : 4400/pub/chat? q = me
Sec-Websocket-Origin : http : // localhost : 800
SEC-Websocket-Protocol : My-Custom-Chat-Protocol
업그레이드 : WebSocket
(도전 응답) : 52 : DF : 2C : F4 : 50 : C2 : 8E : 98 : 14 : B7 : 7D : 09 : CF : C8 : 33 : 40
헤더를 요청하십시오
호스트 : WebSocket Server 호스트
연결 : 연결 유형
업그레이드 : 프로토콜 업그레이드 유형
원산지 : 소스를 방문하십시오
SEC-Websocket-Protocol : Application 자체에 의해 정의 된 옵션, 하위 프로토콜 이름 및 여러 프로토콜은 공백으로 나뉩니다. (*다른 옵션 중 하나는 쿠키입니다)
SEC-WEBSOCKE-KEY1 : 보안 인증 키, XHR 요청은 'SEC-'로 시작하는 요청 헤더를 구할 수 없습니다.
SEC-Websocket-Key2 : 위와 동일합니다
Key3 : 응답 신체 함량, 8 바이트 랜덤.
응답 헤더
SEC-Websocket-Protocol : 요청 된 서브 프로토콜 이름을 포함해야합니다
Sec-Websocket-Origin : 요청 소스와 동일해야합니다.
SEC-Websocket-Location : 요청 된 주소와 같아야합니다
챌린지 응답 : 요청의 세 가지 키 (16 바이트)를 기반으로 계산 된 응답 본문 내용.
응답 문자열 계산 프로세스 의사 코드 :
part_1 = key1의 모든 숫자 / key1 part_2의 공백 수 위와 동일합니다.
32 비트 정수에 대한 big_endian 계산 전략 :
# RGBA 색상 계산과 매우 유사합니다. 다음 함수에서 계산 프로세스 var big_endian = function (n) {return [3,2,1,0] .map (function (i) {return n >> 8*i & 0xff});} big_endian (0xcc77aaff); //-> [204, 119, 170, 255]2. 데이터 보내기
WebSocket API는 이벤트를 사용하여 데이터를 처리하도록 설계되었습니다. 클라이언트는 버퍼를 수동으로 처리하지 않고 이벤트 알림을받는 한 완전한 데이터를 얻을 수 있습니다.
이 경우 각 데이터를 프레임이라고합니다. 사양 정의에서 헤드는 0x00으로 시작해야하며 꼬리 속성은 0xff로 끝나야하므로 각 데이터 전송에는 적어도 두 바이트가 있습니다.
서버 구현에서는 데이터를 수신 할 때 헤드와 테일을 차단해야합니다. 데이터를 보낼 때 헤드와 테일을 포장해야합니다. 형식은 다음과 같습니다.
# 'hello'원본 이진 표현, 요청 헤더 및 여기에 UTF8 인코딩이 있습니다.
<버퍼 E4 BD A0 E5 A5 BD>
# 래핑 된 이진 표현.
<버퍼 00 E4 BD A0 E5 A5 BD FF>
위의 내용은이 기사에 관한 모든 것입니다. 모든 사람의 학습에 도움이되기를 바랍니다.