برنامه نویسی

WebSockets 101 – انجمن DEV

WebSockets یک پروتکل تمام دوطرفه، دوطرفه و مبتنی بر TCP را پیاده سازی می کند که با ws(s)://، که ارتباط دائمی بین مشتری و سرور را امکان پذیر می کند.

چرا به سوکت های وب نیاز است؟

زمانی که سوکت‌های وب چیزی نبود، نظرسنجی HTTP برای هدفی مشابه استفاده می‌شد. HTTP اساسا یک پروتکل یک طرفه است که در آن a مشتری a می فرستد request به سرور، سرور درخواست را می پذیرد و الف می فرستد response. سرور نمی تواند پاسخی را ارسال کنید که هیچ درخواستی از سوی مشتری ارسال نشده است. به زبان ساده، فقط به آنچه خواسته شده پاسخ می دهد.

این نوع رفتار برای برنامه های بلادرنگ مشکل ایجاد می کند. اگر سرور نیاز داشته باشد اطلاعاتی را برای مشتری ارسال کند اما مشتری هنوز از آن اطلاعی نداشته باشد؟ نمی تواند بدون درخواست پاسخی را آغاز کند.

برای غلبه بر این نوع موقعیت ها، از راه حلی استفاده می شود که به آن معروف است polling. کلاینت فرض می کند که ممکن است چیزی وجود داشته باشد که بعداً از سرور مورد نیاز خواهد بود و درخواست های دوره ای را در فواصل زمانی خاص به سرور می فرستد. درخواست های نظرسنجی برای بررسی اینکه آیا چیز جدیدی وجود دارد. اگر چیز جدیدی برای ارسال سرور وجود نداشته باشد، فقط با یک پاسخ خالی پاسخ می دهد. این رویکرد به عنوان شناخته شده است نظرسنجی کوتاه.

تصویر نظرسنجی کوتاه

نظرسنجی طولانی یک رویکرد مشابه است نظرسنجی کوتاه به جز این واقعیت که سرور با یک پاسخ خالی به درخواست نظرسنجی توسط مشتری پاسخ نمی دهد. در عوض، درخواست را دریافت می‌کند، اتصال را باز نگه می‌دارد و تنها زمانی به آن پاسخ می‌دهد که واقعاً چیز جدیدی وجود داشته باشد که باید برای مشتری ارسال شود. پس از اینکه سرور پاسخی را با مقداری داده ارسال کرد، مشتری درخواست نظرسنجی دیگری را فوراً یا پس از تأخیر ارسال می کند. اینگونه است که سرور در واقع قادر است آغازکردن ارتباطی که در پروتکل HTTP سنتی امکان پذیر نیست.

تصویر نظرسنجی طولانی

هر دو روش فوق دارای معایب خاص خود هستند که منجر به استفاده از وب سوکت ها می شود.

کار از وب سوکت ها

سوکت های وب به مشتری اجازه می دهند همچنین سرور برای شروع ارسال پیام. پروتکل وب سوکت شامل یک فرآیند دو قسمتی است. بخش اول شامل الف دست دادن و بخش دوم شامل تبادل است داده ها.

تصویر سوکت وب

دست دادن اولیه زمانی اتفاق می افتد که مشتری یک درخواست HTTP 1.1 را با یک به سرور ارسال می کند upgrade هدر تنظیم شده است websocket. این به سادگی به این معنی است که مشتری به سرور اطلاع می دهد که این اتصال یک اتصال HTTP معمولی نیست، بلکه باید به یک اتصال وب سوکت ارتقا یابد.

درخواست مشتری چیزی شبیه به این است:

GET ws://localhost:5000/ HTTP/1.1
Host: localhost:5000
Connection: Upgrade
Upgrade: websocket
Origin: http://localhost:3000
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: VloOROMIOo0curA7dETByw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوع اتصال در درخواست فوق روی تنظیم شده است ارتقا دهید و پروتکل ارتقا تنظیم شده است سوکت وب. را upgrade هدر می تواند فقط در درخواست های HTTP 1.1 برای ارتقاء به پروتکل دیگری استفاده شود.

را sec-websocket-version، sec-websocket-key، و sec-websocket-extensions هدرهای ویژه ای هستند که توسط مشتری برای توصیف بیشتر اتصال وب سوکت ارسال می شوند.

اکنون که درخواست کلاینت ارسال شده است، سرور درخواست را تأیید می کند (برای اطمینان از اینکه یک اتصال وب سوکت واقعی است)، در صورت پشتیبانی از اتصال وب سوکت، درخواست را می پذیرد و پاسخ تأیید را برمی گرداند.

تأیید درخواست به شرح زیر انجام می شود:

  • سرور به دو اطلاعات نیاز دارد — sec-websocket-key و GUID برای تایید درخواست
  • سپس عملیات لازم را روی این اطلاعات انجام می دهد و a را استخراج می کند sec-websocket-accept مقداری که بعداً به عنوان هدر پاسخ برای مشتری ارسال می شود. این مقدار به مشتری می گوید که سرور اتصال را پذیرفته است و اکنون می تواند مقدار را تأیید کند.

را sec-websocket-accept هدر تنها چیزی نیست که باید بدانیم آیا سرور اتصال را پذیرفته است یا خیر. همچنین یک کد وضعیت وجود دارد 101 که باید برای تکرار پذیرش اتصال توسط سرور وجود داشته باشد. هر کد وضعیت غیر از 101 می گوید که اتصال وب سوکت کامل نیست.

پاسخ سرور چیزی شبیه به این است:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 30RLwsqJ/mc0ojx6XVmAQTDJSvY=
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حال در این مرحله هم کلاینت و هم سرور آماده دریافت پیام از یکدیگر هستند.

نمونه websocket به رویدادهای مختلفی مانند onopen، onclose، onmessageو غیره برای انجام برخی عملیات در هنگام وقوع این رویدادها.

برای درک بهتر جریان پیام ها و رویدادهای مختلف، بیایید یک برنامه کاربردی کوچک بسازیم که سوکت های وب را پیاده سازی می کند.

ساخت یک برنامه وب سوکت

به منظور پیاده سازی وب سوکت ها، می توانید از یک کتابخانه nodejs به نام استفاده کنید ws. این یک راه سریع و ساده برای ایجاد یک اتصال وب سوکت ارائه می دهد.

سرور وب سوکت

npm install ws
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مرحله اول، شما به یک سرور برای رسیدگی به درخواست های وب سوکت نیاز دارید. را ws کتابخانه یک رابط به نام ارائه می دهد WebSocketServer برای ایجاد یک سرور وب سوکت.

// server.mjs
import { WebSocketServer } from "ws"
const wsServer = new WebSocketServer({ port: 5000 })
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس، می توانید شروع به پیوست کردن رویدادها به این سرور کنید.

wsServer.on("connection", (req, ws) => {
    //...
})
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر زمان که سرور یک درخواست اتصال جدید از یک کلاینت دریافت کند، رویداد فوق فعال می شود. این یک تابع پاسخ به تماس را با websocket نمونه، مثال (برای یک مشتری خاص) و شی درخواست.

wsServer.on("connection", (req, ws) => {
    const currentClient = req.headers['sec-websocket-key']
    console.log(`\n\n${currentClient} just got connected\nclients connected: ${wsServer.clients.size}\n`)
})
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شما می توانید از شی درخواست در مورد استفاده کنید sec-websocket-key مقدار هدر، که من از آن برای شناسایی مشتری استفاده کرده ام. در تولید باید یک شناسه منحصر به فرد توسط خودتان ایجاد کنید. این فقط برای اهداف نمایشی است. با استفاده از کد بالا می توانید اتصال کلاینت را روی سرور وارد کنید.

در مرحله بعد، بیایید ببینیم چگونه می‌توانید پیامی را برای همه مشتریان متصل به سرور به جز مشتری فعلی پخش کنید.

بنابراین، در اینجا یک تابع است که یک شیء پیام را می پذیرد و آن را برای همه مشتریان به جز کسی که آن را ارسال می کند، پخش می کند.

function broadcast(message) {

    const stringifiedMessage = JSON.stringify(message)

    wsServer.clients.forEach(client => {
        if (client !== ws && client.readyState === WebSocket.OPEN) {
            client.send(stringifiedMessage, (err) => {
                if (err) {
                    console.log(err)
                    return;
                }
            })
        }
    })
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سرور وب سوکت – wsServer، به تمام کلاینت های متصل به آن دسترسی دارد. را ws خود نمونه websocket مشتری را توصیف می کند. بنابراین، می‌توانید مشتری را در برابر جریان تأیید کنید ws نمونه و بر اساس آن پیام را ارسال کنید.

همچنین، پیام تنها در صورتی باید ارسال شود که اتصال وب سوکت همچنان باز باشد. اگر ارتباط مشتری قطع شود، پیام ارسال نخواهد شد.

اما، اگر بخواهیم فقط به مشتری فعلی پیام ارسال کنیم، چه؟ برای آن، شما به سادگی باید این کار را انجام دهید:

ws.send(message, err => console.log)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را error رویداد websocket به شما این امکان را می دهد که اگر مشکلی پیش آمد وارد شوید.

ws.on("error", console.error)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر زمان که یک کلاینت پیامی به سرور می فرستد، message رویدادی فعال می شود که در صورت تمایل می توانید پیام را برای همه مشتریان پخش کنید.

ws.on('message', (data) => {

    const incomingMessage = data.toString('utf8')

    const outgoingMessage = {
        from: currentClient,
        data: incomingMessage,
        type: {
            isConnectionMessage: false
        }
    }

    broadcast(outgoingMessage)
})
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را data رویداد پیام یک بافر خواهد بود، بنابراین باید آن را به یک رشته تجزیه کنید.

شما همچنین می توانید پخش a مشتری قطع شد در صورت قطع ارتباط یک کلاینت خاص، به همه مشتریان متصل پیام دهید.

ws.on("close", () => {
    console.log(`\n\n${currentClient} closed the connection\nRemaining clients ${wsServer.clients.size}\n`)

    broadcast({
        from: currentClient,
        data: `${currentClient} just left the chat`,
        type: {
            isConnectionMessage: false,
            isDisconnectionMessage: true
        }
    })
})
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کلاینت WebSocket

کلاینت وب سوکت چیزی نیست جز یک صفحه وب با جاوا اسکریپت سمت کلاینت. باید از بومی استفاده کنید WebSocket API ارائه شده توسط مرورگر برای ایجاد یک اتصال وب سوکت.

const ws = new WebSocket("ws://localhost: 5000")
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مال مشتری ws نمونه به رویدادهای مشابهی دسترسی دارد open، close، messageو غیره زیرا اساساً یک نمونه اتصال وب سوکت است.

ws.onopen = () => { }
ws.onclose = () => { }

ws.onmessage = () => {
    console.log(message)
}

ws.send(message)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چندین نمونه مرورگر (یا زبانه ها) متصل به یک سرور وب سوکت می تواند هدف چندین مشتری را تامین کند.

خودشه. اکنون می توانید پیام هایی را به سرور ارسال کنید و مشاهده کنید که چگونه آنها به چندین مشتری متصل پخش می شوند.

موارد استفاده

  • همکاری در زمان واقعی
  • برنامه های چت
  • بازی چند نفره
  • فیدهای زمان واقعی
  • بارگذاری مجدد مرورگر زنده

در اینجا مخزن github حاوی کل کد است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا