WebSocket â Ñе пÑоÑокол, опиÑаний Ñ ÑпеÑиÑÑкаÑÑÑ RFC 6455, Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑÑÑ ÑпоÑÑб обмÑÐ½Ñ Ð´Ð°Ð½Ð¸Ð¼Ð¸ мÑж бÑаÑзеÑом Ñ ÑеÑвеÑом ÑеÑез поÑÑÑйне зâÑднаннÑ. ÐÐ°Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° пеÑедаваÑи в обоÑ
напÑÑмкаÑ
Ñ Ð²Ð¸Ð³Ð»ÑÐ´Ñ âпакеÑÑвâ, без ÑозÑÐ¸Ð²Ñ Ð·âÑÐ´Ð½Ð°Ð½Ð½Ñ Ñа додаÑковиÑ
HTTP-запиÑÑв.
WebSocket вÑдмÑнно пÑÐ´Ñ Ð¾Ð´Ð¸ÑÑ Ð´Ð»Ñ ÑеÑвÑÑÑв, Ñо поÑÑебÑÑÑÑ Ð±ÐµÐ·Ð¿ÐµÑеÑвного обмÑÐ½Ñ Ð´Ð°Ð½Ð¸Ð¼Ð¸, напÑиклад онлайн-ÑгÑи, ÑиÑÑеми ÑоÑгÑÐ²Ð»Ñ Ð² ÑеалÑÐ½Ð¾Ð¼Ñ ÑаÑÑ ÑоÑо.
ÐÑоÑÑий пÑиклад
Щоб вÑдкÑиÑи зâÑÐ´Ð½Ð°Ð½Ð½Ñ websocket, нам поÑÑÑбно ÑÑвоÑиÑи обâÑÐºÑ new WebSocket викоÑиÑÑовÑÑÑи ÑпеÑÑалÑний пÑоÑокол ws в URL-адÑеÑÑ:
let socket = new WebSocket("ws://javascript.info");
Також ÑÑнÑÑ Ð·Ð°ÑиÑÑований пÑоÑокол wss://. Це Ñк HTTPS Ð´Ð»Ñ Ð²ÐµÐ±ÑокеÑÑв.
wss://ÐÑоÑокол wss:// не ÑÑлÑки заÑиÑÑований, але й бÑлÑÑ Ð½Ð°Ð´Ñйний.
Це ÑомÑ, Ñо Ð´Ð°Ð½Ñ ws:// не заÑиÑÑÐ¾Ð²Ð°Ð½Ñ Ñа Ð²Ð¸Ð´Ð¸Ð¼Ñ Ð´Ð»Ñ Ð±ÑдÑ-Ñкого поÑеÑедника. СÑаÑÑ Ð¿ÑокÑÑ-ÑеÑвеÑи не знаÑÑÑ Ð¿Ñо WebSocket, Ñож вони можÑÑÑ Ð¿Ð¾Ð±Ð°ÑиÑи âдивнÑâ заголовки Ñа пеÑеÑваÑи зâÑднаннÑ.
Ð ÑнÑого бокÑ, wss:// â Ñе WebSocket Ñо викоÑиÑÑовÑÑ TLS (Ñак Ñамо, Ñк HTTPS â Ñе HTTP Ñо викоÑиÑÑовÑÑ TLS), ÑобÑо ÑÑÐ²ÐµÐ½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ ÑÑанÑпоÑÑÑ ÑиÑÑÑÑ Ð´Ð°Ð½Ñ Ñ Ð²ÑдпÑавника Ñа ÑозÑиÑÑовÑÑ Ð² одеÑжÑваÑа. Таким Ñином, пакеÑи даниÑ
пеÑедаÑÑÑÑÑ Ð·Ð°ÑиÑÑованими, пÑокÑÑ Ð½Ðµ можÑÑÑ Ð¿Ð¾Ð±Ð°ÑиÑи, Ñо вÑеÑединÑ, Ñ Ð¿ÑопÑÑкаÑÑÑ ÑÑ
.
ÐÑÑÐ»Ñ Ñого, Ñк ÑÐ¾ÐºÐµÑ ÑÑвоÑено, ми Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð¿ÑоÑлÑÑ Ð¾Ð²ÑваÑи його подÑÑ. ÐÑÑго ÑÑ 4:
openâ зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð²ÑÑановлено,messageâ оÑÑÐ¸Ð¼Ð°Ð½Ñ Ð´Ð°Ð½Ñ,errorâ помилка websocket,closeâ зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÐºÑиÑе.
â¦Ð ÑкÑо ми Ñ
оÑемо ÑоÑÑ Ð½Ð°Ð´ÑÑлаÑи, Ñо виклик socket.send(data) зÑобиÑÑ Ñе.
ÐÑÑ Ð¿Ñиклад:
let socket = new WebSocket("wss://javascript.info/article/websocket/demo/hello");
socket.onopen = function(e) {
alert("[open] ÐâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð²ÑÑановлено");
alert("ÐÑдпÑавка на ÑеÑвеÑ");
socket.send("Ðене зваÑи Ðжон");
};
socket.onmessage = function(event) {
alert(`[message] ÐÐ°Ð½Ñ Ð¾ÑÑÐ¸Ð¼Ð°Ð½Ñ Ñз ÑеÑвеÑа: ${event.data}`);
};
socket.onclose = function(event) {
if (event.wasClean) {
alert(`[close] ÐâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÐºÑиÑе ÑиÑÑо, код=${event.code} пÑиÑина=${event.reason}`);
} else {
// напÑиклад ÑеÑÐ²ÐµÑ Ð·Ð°Ð²ÐµÑÑив пÑоÑÐµÑ Ð°Ð±Ð¾ меÑежа не пÑаÑÑÑ
// Ñ ÑÑÐ¾Ð¼Ñ Ð²Ð¸Ð¿Ð°Ð´ÐºÑ event.code зазвиÑай доÑÑвнÑÑ 1006
alert('[close] ÐâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð¿ÐµÑеÑвано');
}
};
socket.onerror = function(error) {
alert(`[error]`);
};
ÐÐ»Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑÑÐ¹Ð½Ð¸Ñ ÑÑлей Ñ Ð½ÐµÐ²ÐµÐ»Ð¸ÐºÐ¸Ð¹ ÑеÑÐ²ÐµÑ server.js, напиÑаний на Node.js, Ð´Ð»Ñ Ð¿ÑÐ¸ÐºÐ»Ð°Ð´Ñ Ð²Ð¸Ñе. ÐÑн вÑдповÑÐ´Ð°Ñ âÐÑивÑÑ Ñз ÑеÑвеÑа, Ðжонâ, поÑÑм ÑÐµÐºÐ°Ñ 5 ÑекÑнд Ñ Ð·Ð°ÐºÑÐ¸Ð²Ð°Ñ Ð·âÑднаннÑ.
Таким Ñином, ви побаÑиÑе подÑÑ open â message â close.
ÐÑÑ Ñ Ð²Ñе, ми вже можемо викоÑиÑÑовÑваÑи WebSocket. ÐоÑиÑÑ Ð¿ÑоÑÑо, Ñи не Ñак?
Ð¢ÐµÐ¿ÐµÑ Ð¿Ð¾Ð³Ð¾Ð²Ð¾Ñимо глибÑе.
ÐÑдкÑиÑÑÑ Ð²ÐµÐ±-ÑокеÑа
Ðоли ÑÑвоÑÑÑÑÑÑÑ new WebSocket(url), вÑн поÑÐ¸Ð½Ð°Ñ Ð¿ÑдклÑÑаÑиÑÑ Ð½ÐµÐ³Ð°Ð¹Ð½Ð¾.
ÐÑд ÑÐ°Ñ Ð¿ÑдклÑÑÐµÐ½Ð½Ñ Ð±ÑаÑÐ·ÐµÑ (за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑв) запиÑÑÑ ÑеÑвеÑ: âЧи пÑдÑÑимÑÑÑе ви Websocket?â Ð ÑкÑо ÑеÑÐ²ÐµÑ Ð²ÑдповÑÐ´Ð°Ñ âÑакâ, Ñо Ñозмова пÑодовжÑÑÑÑÑÑ Ð·Ð° пÑоÑоколом WebSocket, Ñкий Ð²Ð·Ð°Ð³Ð°Ð»Ñ Ð½Ðµ Ñ HTTP.
ÐÑÑ Ð¿Ñиклад заголовкÑв бÑаÑзеÑа Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸ÑÑ, зÑобленого new WebSocket("wss://javascript.info/chat").
GET /chat
Host: javascript.info
Origin: https://javascript.info
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
Sec-WebSocket-Version: 13
Originâ джеÑело клÑÑнÑÑÑÐºÐ¾Ñ ÑÑоÑÑнки, напÑикладhttps://javascript.info. ÐбâÑкÑи WebSocket Ñ Ð¿ÐµÑÐµÑ ÑеÑними за ÑвоÑÑ Ð¿ÑиÑодоÑ. ÐÐµÐ¼Ð°Ñ ÑпеÑÑалÑÐ½Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑв Ñи ÑнÑÐ¸Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ñ. СÑаÑÑ ÑеÑвеÑи вÑе одно не можÑÑÑ Ð¾Ð±ÑоблÑÑи WebSocket, ÑÐ¾Ð¼Ñ Ð¿Ñоблем Ñз ÑÑмÑÑнÑÑÑÑ Ð½ÐµÐ¼Ð°Ñ. Ðле заголовокOriginважливий, оÑкÑлÑки вÑн дозволÑÑ ÑеÑвеÑÑ Ð²Ð¸ÑÑÑÑваÑи, ÑпÑлкÑваÑиÑÑ Ñи Ð½Ñ WebSocket з Ñим веб-ÑайÑом.Connection: Upgradeâ ÑигналÑзÑÑ Ð¿Ñо Ñе, Ñо клÑÑÐ½Ñ Ñ Ð¾Ñе змÑниÑи пÑоÑокол.Upgrade: websocketâ запиÑÑваний пÑоÑокол â âwebsocketâ.Sec-WebSocket-Keyâ випадковий клÑÑ, згенеÑований бÑаÑзеÑом, Ñкий викоÑиÑÑовÑÑÑÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑÐµÐ½Ð½Ñ Ð¿ÑдÑÑимки ÑеÑвеÑом пÑоÑÐ¾ÐºÐ¾Ð»Ñ WebSocket. ÐÑн Ñ Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¸Ð¼, Ñоб пÑокÑÑ-ÑеÑвеÑи не кеÑÑвали бÑдÑ-ÑÐºÑ Ð½Ð°ÑÑÑÐ¿Ð½Ñ Ð¿Ð¾Ð²ÑдомленнÑ.Sec-WebSocket-Versionâ веÑÑÑÑ Ð¿ÑоÑÐ¾ÐºÐ¾Ð»Ñ WebSocket, 13 Ñ Ð¿Ð¾ÑоÑноÑ.
Ðи не можемо викоÑиÑÑаÑи XMLHttpRequest або fetch Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñакого ÑÐ¾Ð´Ñ HTTP-запиÑÑв, оÑкÑлÑки JavaScript забоÑонено вÑÑановлÑваÑи ÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¸.
ЯкÑо ÑеÑÐ²ÐµÑ Ð¿Ð¾Ð³Ð¾Ð´Ð¶ÑÑÑÑÑÑ Ð¿ÐµÑейÑи на WebSocket, вÑн повинен надÑÑлаÑи вÑдповÑÐ´Ñ Ð· кодом 101:
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hsBlbuDTkk24srzEOTBUlZAlC2g=
ТÑÑ Sec-WebSocket-Accept â Ñе Sec-WebSocket-Key, пеÑекодований за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÑпеÑÑалÑного алгоÑиÑмÑ. ÐÑаÑÐ·ÐµÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑ Ð¹Ð¾Ð³Ð¾, Ñоб пеÑеконаÑиÑÑ, Ñо вÑдповÑÐ´Ñ Ð²ÑдповÑÐ´Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑ.
ÐÑÑÐ»Ñ ÑÑого Ð´Ð°Ð½Ñ Ð¿ÐµÑедаÑÑÑÑÑ Ð¿Ð¾ пÑоÑÐ¾ÐºÐ¾Ð»Ñ WebSocket, ÑкоÑо ми побаÑимо його ÑÑÑÑкÑÑÑÑ (âÑÑеймиâ). Ð Ñе зовÑÑм не HTTP.
РозÑиÑÐµÐ½Ð½Ñ Ñа пÑдпÑоÑоколи
ÐожÑÑÑ Ð±ÑÑи додаÑÐºÐ¾Ð²Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¸ Sec-WebSocket-Extensions Ñа Sec-WebSocket-Protocol, ÑÐºÑ Ð¾Ð¿Ð¸ÑÑÑÑÑ ÑозÑиÑÐµÐ½Ð½Ñ Ñа пÑдпÑоÑоколи.
ÐапÑиклад:
-
Sec-WebSocket-Extensions: deflate-frameознаÑаÑ, Ñо бÑаÑÐ·ÐµÑ Ð¿ÑдÑÑимÑÑ ÑÑиÑÐ½ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ . РозÑиÑеннÑ(extension) â Ñе ÑоÑÑ, повâÑзане з пеÑедаÑÐµÑ Ð´Ð°Ð½Ð¸Ñ , ÑобÑо ÑÑнкÑÑоналÑнÑÑÑÑ, Ñка ÑозÑиÑÑÑ Ð¿ÑоÑокол WebSocket. ÐаголовокSec-WebSocket-ExtensionsавÑомаÑиÑно надÑилаÑÑÑÑÑ Ð±ÑаÑзеÑом Ð·Ñ ÑпиÑком ÑÑÑÑ ÑозÑиÑенÑ, ÑÐºÑ Ð²Ñн пÑдÑÑимÑÑ. -
Sec-WebSocket-Protocol: soap, wampознаÑаÑ, Ñо ми Ñ Ð¾Ñемо пеÑедаÑи не пÑоÑÑо бÑдÑ-ÑÐºÑ Ð´Ð°Ð½Ñ, а Ð´Ð°Ð½Ñ Ð² SOAP або WAMP (âThe WebSocket Application Messaging Protocolâ). ÐÑдпÑоÑоколи WebSocket заÑеÑÑÑÑÐ¾Ð²Ð°Ð½Ñ Ð² каÑÐ°Ð»Ð¾Ð·Ñ IANA. ÐÑже, Ñей заголовок опиÑÑÑ ÑоÑмаÑи Ð´Ð°Ð½Ð¸Ñ , ÑÐºÑ Ð¼Ð¸ збиÑаÑмоÑÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑваÑи.Цей необовâÑзковий заголовок вÑÑановлÑÑÑÑÑÑ Ð·Ð° Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ Ð´ÑÑгого паÑамеÑÑа
new WebSocketÑ Ð²Ð¸Ð³Ð»ÑÐ´Ñ Ð¼Ð°ÑÐ¸Ð²Ñ Ð¿ÑдпÑоÑоколÑв. ÐапÑиклад, ÑкÑо ми Ñ Ð¾Ñемо викоÑиÑÑовÑваÑи SOAP або WAMP:let socket = new WebSocket("wss://javascript.info/chat", ["soap", "wamp"]);
СеÑÐ²ÐµÑ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ вÑдповÑÑÑи Ð·Ñ ÑпиÑком пÑоÑоколÑв Ñ ÑозÑиÑенÑ, ÑÐºÑ Ð²Ñн погоджÑÑÑÑÑÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑваÑи.
ÐапÑиклад, запиÑ:
GET /chat
Host: javascript.info
Upgrade: websocket
Connection: Upgrade
Origin: https://javascript.info
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: deflate-frame
Sec-WebSocket-Protocol: soap, wamp
ÐÑдповÑдÑ:
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hsBlbuDTkk24srzEOTBUlZAlC2g=
Sec-WebSocket-Extensions: deflate-frame
Sec-WebSocket-Protocol: soap
ТÑÑ ÑеÑÐ²ÐµÑ Ð²ÑдповÑдаÑ, Ñо пÑдÑÑимÑÑ ÑозÑиÑÐµÐ½Ð½Ñ âdeflate-frameâ, Ñ ÑÑлÑки SOAP Ñз запиÑÑÐ²Ð°Ð½Ð¸Ñ Ð¿ÑдпÑоÑоколÑв.
ÐеÑедаÑа даниÑ
ÐвâÑзок WebSocket ÑкладаÑÑÑÑÑ Ð· âÑÑеймÑвâ â ÑÑагменÑÑв Ð´Ð°Ð½Ð¸Ñ , ÑÐºÑ Ð¼Ð¾Ð¶ÑÑÑ Ð±ÑÑи вÑдпÑÐ°Ð²Ð»ÐµÐ½Ñ Ð±ÑдÑ-ÑÐºÐ¾Ñ ÑÑоÑÐ¾Ð½Ð¾Ñ Ñ Ð¼Ð¾Ð¶ÑÑÑ Ð±ÑÑи кÑлÑÐºÐ¾Ñ Ð²Ð¸Ð´Ñв:
- âÑекÑÑÐ¾Ð²Ñ ÑÑеймиâ â мÑÑÑÑÑÑ ÑекÑÑÐ¾Ð²Ñ Ð´Ð°Ð½Ñ, ÑÐºÑ ÑÑоÑони надÑилаÑÑÑ Ð¾Ð´Ð½Ð° однÑй.
- âÑÑейми двÑÐ¹ÐºÐ¾Ð²Ð¸Ñ Ð´Ð°Ð½Ð¸Ñ â â мÑÑÑÑÑÑ Ð±ÑнаÑÐ½Ñ Ð´Ð°Ð½Ñ, ÑÐºÑ ÑÑоÑони надÑилаÑÑÑ Ð¾Ð´Ð½Ð° однÑй.
- âping/pong ÑÑеймиâ викоÑиÑÑовÑÑÑÑÑÑ Ð´Ð»Ñ Ð¿ÐµÑевÑÑки зâÑднаннÑ, надÑилаÑÑÑÑÑ ÑеÑвеÑом, бÑаÑÐ·ÐµÑ ÑеагÑÑ Ð½Ð° Ð½Ð¸Ñ Ð°Ð²ÑомаÑиÑно.
- Ñакож ÑÑнÑÑ âÑÑейм закÑиÑÑÑ Ð·âÑднаннÑâ Ñа кÑлÑка ÑнÑÐ¸Ñ ÑеÑвÑÑÐ½Ð¸Ñ ÑÑеймÑв.
У бÑаÑзеÑÑ Ð¼Ð¸ безпоÑеÑеднÑо пÑаÑÑÑмо ÑÑлÑки з ÑекÑÑовими або двÑйковими ÑÑеймами.
ÐеÑод WebSocket .send() може надÑилаÑи ÑекÑÑÐ¾Ð²Ñ Ð°Ð±Ð¾ двÑÐ¹ÐºÐ¾Ð²Ñ Ð´Ð°Ð½Ñ.
Ðиклик socket.send(body) дозволÑÑ Ð²ÑдпÑавлÑÑи body Ñ Ð²Ð¸Ð³Ð»ÑÐ´Ñ ÑÑдка або двÑÐ¹ÐºÐ¾Ð²Ð¾Ð¼Ñ ÑоÑмаÑÑ, вклÑÑаÑÑи Blob, ArrayBuffer ÑоÑо. ÐÑÑкиÑ
налаÑÑÑÐ²Ð°Ð½Ñ Ð½Ðµ поÑÑÑбно: пÑоÑÑо надÑилайÑе в бÑдÑ-ÑÐºÐ¾Ð¼Ñ ÑоÑмаÑÑ.
Ðоли ми оÑÑимÑÑмо данÑ, ÑекÑÑ Ð·Ð°Ð²Ð¶Ð´Ð¸ надÑ
одиÑÑ Ñ Ð²Ð¸Ð³Ð»ÑÐ´Ñ ÑÑдка. Ð Ð´Ð»Ñ Ð´Ð²ÑйковиÑ
даниÑ
ми можемо вибиÑаÑи мÑж ÑоÑмаÑами Blob Ñ ArrayBuffer.
Це вÑÑановлÑÑÑÑÑÑ Ð²Ð»Ð°ÑÑивÑÑÑÑ socket.binaryType, Ñ Ñипово викоÑиÑÑовÑÑÑÑÑÑ "blob", ÑÐ¾Ð¼Ñ Ð´Ð²ÑÐ¹ÐºÐ¾Ð²Ñ Ð´Ð°Ð½Ñ Ð½Ð°Ð´Ñ
одÑÑÑ Ñк обâÑкÑи Blob.
Blob â Ñе двÑйковий обâÑÐºÑ Ð²Ð¸Ñокого ÑÑвнÑ, вÑн безпоÑеÑеднÑо ÑнÑегÑÑÑÑÑÑÑ Ð· Ñегами <a>, <img> Ñа ÑнÑими, ÑÐ¾Ð¼Ñ Ñе ноÑмалÑне Ñипове знаÑеннÑ. Ðле Ð´Ð»Ñ Ð´Ð²ÑÐ¹ÐºÐ¾Ð²Ð¾Ñ Ð¾Ð±Ñобки, Ñоб оÑÑимаÑи доÑÑÑп до окÑемиÑ
байÑÑв даниÑ
, ми можемо змÑниÑи його на "arraybuffer":
socket.binaryType = "arraybuffer";
socket.onmessage = (event) => {
// event.data Ñ Ð°Ð±Ð¾ ÑÑдком (ÑкÑо ÑекÑÑ) або arraybuffer (ÑкÑо двÑйковий)
};
ÐÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑвидкоÑÑÑ
УÑвÑÑÑ, Ñо Ð½Ð°Ñ Ð´Ð¾Ð´Ð°Ñок генеÑÑÑ Ð±Ð°Ð³Ð°Ñо Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð½Ð°Ð´ÑиланнÑ. Ðле Ñ ÐºÐ¾ÑиÑÑÑваÑа повÑлÑне пÑдклÑÑÐµÐ½Ð½Ñ Ð´Ð¾ меÑежÑ, можливо, ÑеÑез мобÑлÑний ÑнÑеÑÐ½ÐµÑ Ñи погане покÑиÑÑÑ Ð·Ð° мÑÑÑом.
Ðи можемо викликаÑи socket.send(data) Ð·Ð½Ð¾Ð²Ñ Ñ Ð·Ð½Ð¾Ð²Ñ. Ðле Ð´Ð°Ð½Ñ Ð±ÑÑеÑизÑÑÑÑÑÑ (збеÑÑгаÑÑÑÑÑ) Ñ Ð¿Ð°Ð¼âÑÑÑ Ñа надÑилаÑимÑÑÑÑÑ Ð»Ð¸Ñе наÑÑÑлÑки Ñвидко, наÑкÑлÑки Ñе дозволÑÑ ÑвидкÑÑÑÑ Ð¼ÐµÑежÑ.
ÐлаÑÑивÑÑÑÑ socket.bufferedAmount збеÑÑгаÑ, ÑкÑлÑки байÑÑв залиÑилоÑÑ Ñ Ð±ÑÑеÑÑ Ð² Ñей моменÑ, оÑÑкÑÑÑи вÑдпÑÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð¼ÐµÑежеÑ.
Ðи можемо пеÑевÑÑиÑи його, Ñоб побаÑиÑи, Ñи дÑйÑно ÑÐ¾ÐºÐµÑ Ð´Ð¾ÑÑÑпний Ð´Ð»Ñ Ð¿ÐµÑедаÑÑ.
// ÐºÐ¾Ð¶Ð½Ñ 100 Ð¼Ñ Ð¿ÐµÑевÑÑÑÑмо ÑÐ¾ÐºÐµÑ Ñ Ð½Ð°Ð´ÑилаÑмо бÑлÑÑе даниÑ
// ÑÑлÑки ÑкÑо бÑли надÑÑÐ»Ð°Ð½Ñ Ð²ÑÑ Ð½Ð°ÑÐ²Ð½Ñ Ð´Ð°Ð½Ñ
setInterval(() => {
if (socket.bufferedAmount == 0) {
socket.send(moreData());
}
}, 100);
ÐакÑиÑÑÑ Ð·âÑднаннÑ
ÐазвиÑай, коли одна Ð·Ñ ÑÑоÑÑн Ñ Ð¾Ñе закÑиÑи зâÑÐ´Ð½Ð°Ð½Ð½Ñ (Ñ Ð±ÑаÑзеÑ, Ñ ÑеÑÐ²ÐµÑ Ð¼Ð°ÑÑÑ ÑÑÐ²Ð½Ñ Ð¿Ñава), вони надÑилаÑÑÑ âÑÑейм закÑиÑÑÑ Ð·âÑднаннÑâ з ÑиÑÑовим кодом Ñ ÑекÑÑÐ¾Ð²Ð¾Ñ Ð¿ÑиÑиноÑ.
ÐеÑод Ð´Ð»Ñ ÑÑого:
socket.close([code], [reason]);
codeÑе ÑпеÑÑалÑний код закÑиÑÑÑ WebSocket (необовâÑзковий паÑамеÑÑ)reasonÑе ÑÑдок, Ñкий опиÑÑÑ Ð¿ÑиÑÐ¸Ð½Ñ Ð·Ð°ÐºÑиÑÑÑ (необовâÑзковий паÑамеÑÑ)
ÐÑÑÐ»Ñ ÑÑого ÑнÑа ÑÑоÑона в обÑÐ¾Ð±Ð½Ð¸ÐºÑ Ð¿Ð¾Ð´ÑÑ close оÑÑимÑÑ ÐºÐ¾Ð´ Ñ Ð¿ÑиÑинÑ, напÑиклад:
// закÑиваÑÑа ÑÑоÑона:
socket.close(1000, "Work complete");
// ÑнÑа ÑÑоÑона
socket.onclose = event => {
// event.code === 1000
// event.reason === "Work complete"
// event.wasClean === true (clean close)
};
ÐайпоÑиÑенÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ ÐºÐ¾Ð´Ñ Ð·Ð°ÐºÑиÑÑÑ:
1000â Ñипове знаÑеннÑ, звиÑайне закÑиÑÑÑ (викоÑиÑÑовÑÑÑÑÑÑ, ÑкÑо не вказаноcode),1006â Ð½ÐµÐ¼Ð°Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ÑÑÑ Ð²ÑÑановиÑи Ñакий код вÑÑÑнÑ, вказÑÑ Ð½Ð° Ñе, Ñо зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð±Ñло вÑÑаÑено (Ð½ÐµÐ¼Ð°Ñ Ð·Ð°ÐºÑиваÑÑого ÑÑеймÑ).
Рй ÑнÑÑ ÐºÐ¾Ð´Ð¸, напÑиклад:
1001â одна Ð·Ñ ÑÑоÑÑн вÑдклÑÑаÑÑÑÑÑ, напÑиклад ÑеÑÐ²ÐµÑ Ð²Ð¸Ð¼Ð¸ÐºÐ°ÑÑÑÑÑ Ð°Ð±Ð¾ бÑаÑÐ·ÐµÑ Ð·Ð°Ð»Ð¸ÑÐ°Ñ ÑÑоÑÑнкÑ,1009â повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð²ÐµÐ»Ð¸ÐºÐµ Ð´Ð»Ñ Ð¾Ð±Ñобки,1011â неоÑÑкÑвана помилка на ÑеÑвеÑÑ,- â¦Ñ Ñак далÑ.
Ðовний ÑпиÑок можна знайÑи в RFC6455, §7.4.1.
Ðоди WebSocket деÑо ÑÑ
Ð¾Ð¶Ñ Ð½Ð° коди HTTP, але вÑдÑÑзнÑÑÑÑÑÑ. ÐокÑема, бÑдÑ-ÑÐºÑ ÐºÐ¾Ð´Ð¸ менÑе 1000 заÑезеÑвованÑ. ЯкÑо ми ÑпÑобÑÑмо вÑÑановиÑи Ñакий код, виникне помилка.
// Ñ ÑÐ°Ð·Ñ ÑозÑÐ¸Ð²Ñ Ð·Ð²âÑзкÑ
socket.onclose = event => {
// event.code === 1006
// event.reason === ""
// event.wasClean === false (Ð½ÐµÐ¼Ð°Ñ Ð·Ð°ÐºÑиваÑÑого ÑÑеймÑ)
};
СÑан зâÑднаннÑ
Щоб оÑÑимаÑи ÑÑан зâÑднаннÑ, додаÑково Ñ Ð²Ð»Ð°ÑÑивÑÑÑÑ socket.readyState Ð·Ñ Ð·Ð½Ð°ÑеннÑми:
0â âCONNECTINGâ: зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ñе не вÑÑановлено,1â âOPENâ: обмÑн даними,2â âCLOSINGâ: зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÐºÑиваÑÑÑÑÑ,3â âCLOSEDâ: зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÐºÑиÑе.
ÐÑиклад ÑаÑÑ
РозглÑнÑмо пÑиклад ÑаÑÑ Ð· викоÑиÑÑаннÑм WebSocket API бÑаÑзеÑа Ñа модÑÐ»Ñ WebSocket Node.js https://github.com/websockets/ws. Ðи пÑидÑлимо оÑÐ½Ð¾Ð²Ð½Ñ ÑÐ²Ð°Ð³Ñ ÐºÐ»ÑÑнÑÑÑкÑй ÑÑоÑонÑ, але ÑеÑÐ²ÐµÑ Ñакож пÑоÑÑий.
HTML: нам поÑÑÑбна ÑоÑма <form> Ð´Ð»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²ÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ñ Ñа <div> Ð´Ð»Ñ Ð²Ñ
ÑдниÑ
повÑдомленÑ:
<!-- ÑоÑма повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ -->
<form name="publish">
<input type="text" name="message">
<input type="submit" value="Send">
</form>
<!-- div з повÑдомленнÑми -->
<div id="messages"></div>
ÐÑд JavaScript ми Ñ Ð¾Ñемо ÑÑÑÐ¾Ñ ÑеÑей:
- ÐÑдкÑиÑи пÑдклÑÑеннÑ.
- ÐÑд ÑÐ°Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ ÑоÑми â викликаÑи
socket.send(message)Ð´Ð»Ñ Ð¿Ð¾Ð²ÑдомленнÑ. - ÐÑи вÑ
ÑÐ´Ð½Ð¾Ð¼Ñ Ð¿Ð¾Ð²ÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ â додайÑи його до
div#messages.
ÐÑÑ ÐºÐ¾Ð´:
let socket = new WebSocket("wss://javascript.info/article/websocket/chat/ws");
// надÑÑлаÑи повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð· ÑоÑми
document.forms.publish.onsubmit = function() {
let outgoingMessage = this.message.value;
socket.send(outgoingMessage);
return false;
};
// повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¾ÑÑимано - показаÑи повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² div#messages
socket.onmessage = function(event) {
let message = event.data;
let messageElem = document.createElement('div');
messageElem.textContent = message;
document.getElementById('messages').prepend(messageElem);
}
СеÑвеÑний код ÑÑÐ¾Ñ Ð¸ Ð²Ð¸Ñ Ð¾Ð´Ð¸ÑÑ Ð·Ð° Ñамки поÑоÑÐ½Ð¾Ñ Ñеми. ТÑÑ Ð¼Ð¸ бÑдемо викоÑиÑÑовÑваÑи Node.js, але вам не обовâÑзково Ñе ÑобиÑи. ÐнÑÑ Ð¿Ð»Ð°ÑÑоÑми Ñакож маÑÑÑ ÑÐ²Ð¾Ñ Ð·Ð°Ñоби Ð´Ð»Ñ ÑобоÑи з WebSocket.
ÐлгоÑиÑм на ÑÑоÑÐ¾Ð½Ñ ÑеÑвеÑа бÑде Ñаким:
- СÑвоÑиÑи
clients = new Set()â набÑÑ ÑокеÑÑв. - ÐÐ»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ пÑийнÑÑого веб-ÑокеÑа додаÑи його до набоÑÑ
clients.add(socket)Ñ Ð½Ð°Ð»Ð°ÑÑÑваÑи пÑоÑлÑÑ Ð¾Ð²ÑÐ²Ð°Ñ Ð¿Ð¾Ð´ÑÑmessage, Ñоб оÑÑимаÑи повÑдомленнÑ. - Ðоли оÑÑимано повÑдомленнÑ: пеÑеглÑнÑÑи клÑÑнÑÑв Ñа надÑÑлаÑи його вÑÑм.
- Ðоли зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÐºÑиÑо:
clients.delete(socket).
const ws = new require('ws');
const wss = new ws.Server({noServer: true});
const clients = new Set();
http.createServer((req, res) => {
// ÑÑÑ Ð¼Ð¸ обÑоблÑÑмо лиÑе зâÑÐ´Ð½Ð°Ð½Ð½Ñ websocket
// Ñ ÑеалÑÐ½Ð¾Ð¼Ñ Ð¿ÑоекÑÑ Ñ Ð½Ð°Ñ Ð±Ñв би Ñакож код Ð´Ð»Ñ Ð¾Ð±Ñобки запиÑÑв, ÑÐºÑ Ð½Ðµ Ñ Ð²ÐµÐ±-ÑокеÑами
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onSocketConnect);
});
function onSocketConnect(ws) {
clients.add(ws);
ws.on('message', function(message) {
message = message.slice(0, 50); // макÑималÑна довжина повÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±Ñде 50
for(let client of clients) {
client.send(message);
}
});
ws.on('close', function() {
clients.delete(ws);
});
}
ÐÑÑ ÑобоÑий пÑиклад:
Ðи Ñакож можеÑе заванÑажиÑи його (кнопка вгоÑÑ ÑпÑава в iframe) Ñа запÑÑÑиÑи локалÑно. ТÑлÑки не забÑдÑÑе пеÑед запÑÑком вÑÑановиÑи Node.js Ñ npm install ws.
ÐÑдÑÑмки
WebSocket â Ñе ÑÑÑаÑний ÑпоÑÑб маÑи поÑÑÑйне зâÑÐ´Ð½Ð°Ð½Ð½Ñ Ð±ÑаÑзеÑ-ÑеÑвеÑ.
- WebSockets не Ð¼Ð°Ñ ÐºÑоÑÐ´Ð¾Ð¼ÐµÐ½Ð½Ð¸Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ñ.
- ÐÑн добÑе пÑдÑÑимÑÑÑÑÑÑ Ð² бÑаÑзеÑÐ°Ñ .
- Ðоже надÑилаÑи/оÑÑимÑваÑи ÑÑдки Ñа двÑÐ¹ÐºÐ¾Ð²Ñ Ð´Ð°Ð½Ñ.
API пÑоÑÑий.
ÐеÑоди:
socket.send(data),socket.close([code], [reason]).
ÐодÑÑ:
open,message,error,close.
WebSocket Ñам по ÑÐ¾Ð±Ñ Ð½Ðµ вклÑÑÐ°Ñ Ð¿Ð¾Ð²ÑоÑне пÑдклÑÑеннÑ, аÑÑенÑиÑÑкаÑÑÑ Ñа багаÑо ÑнÑÐ¸Ñ Ð²Ð¸ÑокоÑÑÐ²Ð½ÐµÐ²Ð¸Ñ Ð¼ÐµÑ Ð°Ð½ÑзмÑв. Ð¢Ð¾Ð¼Ñ Ð´Ð»Ñ ÑÑого ÑÑнÑÑÑÑ ÐºÐ»ÑÑнÑÑÑÐºÑ Ñа ÑеÑвеÑÐ½Ñ Ð±ÑблÑоÑеки, а Ñакож ÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ÑÑÑ Ð¼Ð¾Ð¶Ð½Ð° ÑеалÑзÑваÑи вÑÑÑнÑ.
ÐнодÑ, Ñоб ÑнÑегÑÑваÑи WebSocket в наÑвний пÑоекÑ, лÑди запÑÑкаÑÑÑ WebSocket-ÑеÑÐ²ÐµÑ Ð¿Ð°ÑалелÑно з оÑновним HTTP-ÑеÑвеÑом, Ñ Ð²Ð¾Ð½Ð¸ ÑпÑлÑно викоÑиÑÑовÑÑÑÑ ÑÐ´Ð¸Ð½Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð¸Ñ
. ÐапиÑи до WebSocket викоÑиÑÑовÑÑÑÑ wss://ws.site.com, ÑÑбдомен, Ñкий веде до ÑеÑвеÑа WebSocket, а https://site.com ÑпÑÑмовÑÑÑÑÑÑ Ð½Ð° оÑновний HTTP-ÑеÑвеÑ.
ÐвÑÑно, Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ Ð¹ ÑнÑÑ ÑлÑÑ Ð¸ ÑнÑегÑаÑÑÑ.
ÐоменÑаÑÑ
<code>, Ð´Ð»Ñ ÐºÑлÑÐºÐ¾Ñ ÑÑдкÑв â обгоÑнÑÑÑ ÑÑ Ñегом<pre>, Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 10 ÑÑдкÑв â викоÑиÑÑовÑйÑе пÑÑоÑниÑÑ (plnkr, jsbin, codepenâ¦)