همانطور که توسعه وب پیشرفت می کند و تکامل می یابد، تجربیات تعاملی و real-time به یک ویژگی مهم تر در برنامه های کاربردی وب مدرن تبدیل می شوند.
با WebSockets، توسعه دهندگان ابزار قدرتمندی برای ساخت برنامه های سریع، کارآمد و پویا real-time دارند. این فناوری نوآورانه ارتباط دو طرفه بین کلاینت و سرور را امکان پذیر می کند و از مدل سنتی پاسخ به درخواست(request) HTTP فاصله می گیرد.
در این مقاله، پیچیدگیهای WebSockets را بررسی میکنیم و با ساختن یک برنامه چت real-time با Vue، پتانسیل آن را بررسی میکنیم.
WebSockets چیست؟
WebSocket یک پروتکل برای ارتباط دوطرفه و real-time بین کلاینت و سرور است. WebSocket که به عنوان بخشی از مشخصات HTML5 معرفی شده است به یکی از محبوب ترین روش ها برای ساخت برنامه های وب real-time تبدیل شده است.
برخلاف ارتباطات سنتی HTTP که بر اساس مدل درخواست-پاسخ(requset-response) عمل میکند، WebSockets امکان ارتباط دو طرفه و مداوم بین کلانیت و سرور را فراهم میکند، به این معنی که کلانیت میتواند درخواستی را به سرور ارسال کند و سرور میتواند درخواستی را برای کلانیت ارسال کند. و بر عکس.
جریان ثابت داده ها بین کلاینت و سرور تضمین می کند که تجربه کاربر یکپارچه است، به طوری که بروز رسانی ها در real-time به جای تازه کردن صفحه(refresh) انجام می شود. HTTP همچنین برای بارگیری صفحات استاتیک محدود و برای ارتباطات حساس به زمان کافی نیست.
WebSockets چگونه کار می کند؟
پروتکل WebSockets روی پروتکل Transmission Control Protocol (TCP)، یک پروتکل ارتباطی سطح پایین که یک اتصال قابل اعتماد و جریان گرا بین دو کامپیوتر فراهم می کند، عمل می کند. قبل از ایجاد اتصال WebSocket، باید چندین مرحله را دنبال کنید.
در طول درخواست اولیه، کلاینت یک درخواست HTTP را با یک هدر خاص با خواندن Upgrade: WebSocket
به سرور ارسال می کند که نشان می دهد می خواهد اتصال را به یک اتصال WebSockets ارتقا دهد.
در مرحله بعد، در طی این فرآیند، سرور درخواست اولیه را دریافت می کند و بررسی می کند که آیا از WebSockets پشتیبانی می کند یا خیر. در این صورت، سرور پاسخی با همان Upgrade: websocket header
و کد وضعیت HTTP 101 Switching Protocols
ارسال می کند که نشان می دهد اتصال در حال ارتقا است. سپس کلاینت و سرور برای اطمینان از ایمن بودن اتصال، کلیدهای اتصال به WebSockets را می فرستد.
هنگامی که این فرآیند کامل شد و کلیدها مطابقت داشتند، اتصال WebSockets برقرار می شود و کلاینت و سرور می توانند داده ها را در هر دو جهت بدون نیاز به چرخه درخواست-پاسخ تبادل کنند. داده ها به صورت بسته از طریق اتصال TCP زیرین ارسال می شوند. این ارتباط تمام دوبلکس(full-duplex) بروز رسانی ها و اعلان ها را در real-time امکان پذیر می کند.
کلاینت یا سرور می توانند اتصال WebSockets را در هر زمان ببندند. پروتکل WebSockets مکانیزمی را برای بسته شدن اتصال فراهم می کند و اجازه می دهد تا داده های باقی مانده قبل از بسته شدن اتصال ارسال شود.
پروتکل WebSockets طوری طراحی شده است که روی همان پورت های HTTP و HTTPS کار کند و ادغام آن در زیرساخت های وب موجود را آسان می کند.
مزایای استفاده از WebSockets
در مقایسه با سایر روشهای ارتباطی سنتی مبتنی بر HTTP، WebSockets دارای مزایای متعددی است که یک روش ارتباطی سریع و کم تاخیر را ارائه میدهد.
WebSockets مربوط به چرخههای سنتی درخواست-پاسخ HTTP را حذف میکند و امکان برقراری ارتباط مداوم و دو طرفه را از طریق یک اتصال واحد فراهم میکند. این امر میزان داده های ارسال شده و تعداد رفت و برگشت مورد نیاز را کاهش می دهد و عملکرد برنامه های real-time را بهبود می بخشد.
WebSockets یک پروتکل استاندارد است که توسط بسیاری از مرورگرهای مدرن پشتیبانی می شود و سازگاری بین مرورگرها را امکان پذیر می کند.
WebSockets همچنین مزیتی نسبت به نظرسنجی دارد که در آن کلاینت همچنان به درخواست داده های جدید از سرور ادامه می دهد حتی اگر داده جدیدی در دسترس نباشد. WebSockets امکان برقراری ارتباط موثرتر و پاسخگو بین کلاینت و سرور را فراهم می کند و آن را به یک راه حل ایده آل برای برنامه های کاربردی real-time تبدیل می کند.
WebSockets events
برای باز کردن اتصال WebSocket، مطابق زیر، شی WebSocket را فراخوانی کنید:
const socket = new WebSocket(url);
هنگامی که اتصال WebSockets ایجاد شد، می توانید رویدادها را هم در کلاینت و هم در سرور راه اندازی کنید. برای گوش دادن به این رویدادها از توابع callback و event listeners استفاده می کنیم. چهار رویداد اصلی open
، message
، error
و close
هستند.
رویداد open
زمانی فعال می شود که یک اتصال با موفقیت برقرار شود. تابع callback برای این رویداد onopen
نامیده می شود:
socket.onopen => (){
console.log("WebSocket connection opened:", event);
};
هنگامی که message
از سرور دریافت می شود، message راه اندازی می شود. دادههای message از طریق ویژگی event.value
قابل دسترسی است:
socket.onmessage => (event) {
console.log("WebSocket message received:", event.value);
};
error
زمانی ایجاد می شود که هنگام تلاش برای برقراری یا حفظ اتصال، خطایی رخ دهد. تابع callback به رویداد خطا یک onerror
است:
socket.onerror => (error) {
console.log("WebSocket error:", error);
};
close
هنگامی که اتصال بسته می شود فعال می شود:
socket.onclose => (event) {
console.log("WebSocket connection closed:", event.code);
};
پروتکل WebSocket چندین روش ارائه می دهد که می توانید از آنها برای انجام اقدامات روی اتصال WebSocket استفاده کنید، از جمله ()send
و ()close
.
ما از روش ()send
برای ارسال داده ها به سرور از طریق اتصال WebSocket استفاده می کنیم. داده ها می توانند یک رشته، یک آرایه باینری باشند:
socket.send("Hello, server!");
ما از متد ()close
برای بستن اتصال WebSocket استفاده می کنیم. این دو پارامتر اختیاری دارد، code
، کد وضعیت، و reason
، یک رشته متنی که دلیل بسته شدن اتصال را مشخص می کند:
socket.close(1000, "Goodbye");
ساخت یک برنامه چت Real-Time
اکنون که با اصول WebSockets آشنا شدیم، بیایید یک مثال عملی را با Vue اجرا کنیم.
برای شروع راه اندازی در IDE ، باید دو پروژه مجزا ایجاد کنیم، یکی برای کلاینت و دیگری برای سرور. این جداسازی امکان مدیریت آسانتر وابستگیها را فراهم میکند و ما را قادر میسازد تا روی هر پروژه به طور مستقل کار کنیم.
ایجاد سرور WebSocket
ws یک کتابخانه محبوب Node.js WebSocket است که استفاده از آن ساده است و به طور کامل برای اجرای سرویس گیرنده و سرور WebSocket آزمایش شده است.
ws روش های ساده و مستقیمی را برای ایجاد سرورهای WebSocket، مدیریت اتصالات دریافتی و ارسال پیام بین کلاینت و سرور ارائه می دهد. با طیف گسترده ای از مرورگرها و پلتفرم ها سازگار است و گزینه های سفارشی سازی و افزونه را ارائه می دهد.
برای راه اندازی پروژه سمت سرور، ابتدا یک پروژه Node.js جدید را با اجرای npm init
و دنبال کردن دستورات برای ایجاد فایل package.json
مقداردهی اولیه کنید. سپس یک فایل جدید به نام server.js
در ریشه دایرکتوری پروژه سرور ایجاد کنید.
برای ایجاد WebSocket و راه اندازی سرور، به ترتیب باید کتابخانه ws
و Express
را نصب کنید:
npm install ws, express
ما از Express برای ایجاد یک نمونه وب سرور استفاده می کنیم که درخواست ها و پاسخ های HTTP را مدیریت می کند. سپس این سرور به سازنده WebSocket ارسال می شود تا یک سرور WebSocket ایجاد کند:
// Import required modules
const express = require("express");
const http = require("http");
const WebSocket = require("ws");
// Create an Express app instance
const app = express();
// Create an HTTP server using the Express app instance
const server = http.createServer(app);
// Create a WebSocket server instance and attach it to the HTTP server
const websocketServer = new WebSocket.Server({ server });
// Start the server listening on port 3000
server.listen(3000, () => {
console.log("Websocket server started on port 3000");
});
هنگامی که پایه سرور را راه اندازی کردیم، می توانیم رویدادهای WebSocket را برای مدیریت برنامه چت ایجاد کنیم:
//Listen for WebSocket connections
websocketServer.on('connection', (socket) => {
// Log a message when a new client connects
console.log('client connected.');
// Listen for incoming WebSocket messages
socket.on('message', (data) => {
// Broadcast the message to all connected clients
websocketServer.clients.forEach(function each(client) {
if (client !== socket && client.readyState === WebSocket.OPEN) {
client.send(data.toString());
// console.log("message",data.toString())
}
});
});
// Listen for WebSocket connection close events
socket.on('close', () => {
// Log a message when a client disconnects
console.log('Client disconnected');
});
});
کد بالا یک سرور WebSocket ساده را راه اندازی می کند که می تواند اتصالات ورودی، پیام ها و قطع ارتباط را مدیریت کند. هنگامی که یک سرویس گیرنده پیامی را ارسال می کند، سرور پیام را برای همه کلاینت های متصل به جز فرستنده ارسال می کند.
ساخت بخش فرانت اند
برای راهاندازی سمت کلاینت برنامه، از Vue برای توسعه رابط کاربری استفاده میکنیم و سپس با استفاده از شی WebSocket به سرور WebSocket متصل میشویم.
WebSocket API مجموعه ای از روش ها و رویدادها را ارائه می دهد که به ما امکان می دهد با WebSockets روی کلاینت کار کنیم. اینها شامل سازنده ()WebSocket
است که یک شی WebSocket جدید ایجاد می کند و اتصالی را با URL مشخص شده برقرار می کند، متد ()send
که داده ها را به سرور ارسال می کند و رویدادهای onopen
، onmessage
، onerror
و onclose
که مدیریت می کنند. وضعیت اتصال و داده های ورودی:
const socket = new WebSocket('ws://localhost:3000')
کد بالا شی WebSocket را مقداردهی اولیه می کند و سپس URL را به جایی که سرور شما میزبانی شده است ارسال می کند.
برای برنامه چت، ما یک رابط کاربری ساده ایجاد خواهیم کرد که با یک modal برای ذخیره نام کاربر شروع می شود، سپس صفحه ای را با کادر ورودی برای پیام هایی که بین کلاینت و سرور ارسال می شود، نمایش می دهد.
ابتدا با استفاده از Vue CLI با اجرای دستور زیر یک پروژه جدید ایجاد کنید:
vue create socket-chat
برای سازماندهی پروژه، یک کامپوننت چت جداگانه ایجاد می کنیم، سپس کد زیر را برای تعریف ساختار قالب صفحه قرار می دهیم:
<template>
<div class="chat-container">
<!-- Name Input window -->
<div v-if="!connect">
<div class="modal-background">
<div class="modal-content">
<form @submit.prevent="handleSubmit">
<h3> Enter your name to start chatting </h3>
<input type="text" v-model="username" placeholder="Enter your name" />
<br>
<button type="submit"> Connect </button>
</form>
</div>
</div>
</div>
<div v-if="connect" class="chat-window">
<div class="messages-container">
<!-- <ul> -->
<!-- Use a v-for directive to iterate over the messages array and display each message -->
<div v-for="(val, index) in messages" :key="index" :class="[val.username === username ? 'left-bubble' : 'right-bubble']">
<!-- Use mustache syntax to interpolate the username and message properties of each message object -->
<b>{{ val.username }}</b>: <em>{{ val.message }}</em>
</div>
<!-- </ul> -->
</div>
<div class="chat-input">
<form @submit.prevent="handleMessageSubmit(username,text)">
<!-- Use v-model directive to bind the text input to the 'text' variable -->
<input type="text" v-model="text" placeholder="Write message..." />
<button type="submit"><i class="bi bi-send "></i> </button>
</form>
</div>
</div>
</div>
</template>
برای افزودن قابلیت به برنامه، از سه عملکرد اصلی استفاده خواهیم کرد. برای یکی، تابع handleConnect
بررسی می کند که آیا کاربر نامی را وارد کرده است یا خیر، سپس اتصال را به true اختصاص می دهد:
const handleConnect = () => {
if(username.value.length > 0) {
connect.value = true
}
}
SendMessage
نام کاربری و متن را در یک شی ذخیره می کند، سپس شیء را با استفاده از روش ارسال به سرور ارسال می کند. همچنین با استفاده از متد ()JSON.stringify
شی را به رشته تبدیل می کند:
const sendMessage = (username,text) => {
const messageData = { username: username, message: text};
// Send the message data to the server using WebSockets
socket.send(JSON.stringify(messageData))
// Add the message data to the messages array
messages.value.push(messageData)
}
برای دریافت پیامها از سرور، از رویداد onmessage
استفاده میکنیم، سپس دادههای رشته را با استفاده از روش ()JSON.parse
به شی جاوا اسکریپت تبدیل میکنیم:
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
messages.value.push(message);
}
خب، ما با موفقیت یک برنامه چت real-time ایجاد کرده ایم که می تواند یک پیام را بین چندین کلاینت ارسال کند.