چطور websocket را پیاده سازی کنیم؟ مثلاً می خواهیم یک سیستم چتینگ داشته باشیم که بصورت real time پیام ها را ارسال کند و آنلاین بودن کاربران را نشان دهد
- نفیسه افقی 1 سال قبل سوال کرد
- آخرین ویرایش 1 سال قبل
- شما باید برای ارسال دیدگاه وارد شوید
فرض کنید یک اپلیکیشن چت نوشتیم و می خواهیم بصورت real time پیام ها را نمایش دهیم. یعنی وقتی کاربر1 به کاربر2 پیام می فرستد، نیازی به رفرش کردن صفحه نباشد. یا مثلاً وقتی کاربر1 وارد صفحه چت شد، آنلاین بودنش به تمامی دوستانش نمایش داده شود. برای این طور کارها از مفهومی بنام websocket استفاده می کنیم.
websocket نوعی از کانکشن است. برعکس کانکشن http که بعد از ارسال داده بسته می شود، websocket کانکشنی است که تا زمانیکه دو طرف بخواهند باز می ماند و می توان بینشان داده رد و بدل کرد. کانکشن websocket به جای http با ws شروع می شود.
حالا چطور از websocket استفاده کنیم؟
websocket را باید برای server و client جدا پیاده سازی کنیم.
اول لازم است تا روی سرور یک gateway باز کنیم. gateway سروری است که روی یک پورت بالا می آید و همیشه بالا است. client ها با websocket به آن connect و disconnect می شوند، message ارسال می کنند و به تمامی message هایی که ارسال می شود گوش می دهند. (gateway هم می تواند به تمامی client هایی که وصل هستند، یک message را ارسال کند)
مثلاً وقتی کاربر1 وارد چت می شود، با یک websocket به gateway وصل می شود. حالا ما می توانیم به تمامی کاربرانی که داخل آن چت روم هستند آنلاین شدن کاربر1 را اطلاع دهیم. یا اگر کاربر1 پیامی به کاربر2 ارسال کند، پیام را بلافاصله به کاربر2 ارسال کنیم. (چون کاربر2 هم به gateway متصل است)
برای مثال، ما اینجا در سمت client از react استفاده می کنیم و در سمت سرور از nest.js
سمت سرور
یک پروژه nest.js بسازید. بهتر است پروژه websocket را از پروژه اصلی back-end تان جدا کنید. (تا به تداخل depency ها برنخورید. می توانید هر کدام را هم روی یک پورت جدا بالا بیاورید)
کتابخانه های زیر را نصب کنید:
npm install socket.io @nestjs/websockets
داخل فولدر src
پروژه یک فولدر بنام websocket
بسازید و دو فایل با نامهای websocket.module.ts
و websocket.service.ts
بسازید.
فایل یک ماژول است که باید فایل را به عنوان provider برایش تعریف کنید:
// websocket.module.ts
import { Module } from '@nestjs/common';
import { WebSocketService } from './websocket.service'; // Import your WebSocket gateway
@Module({
providers: [WebSocketService], // Add your WebSocket gateway here
})
export class WebSocketModule {}
باید داخل فایل app.module.ts
هم ماژولی که ساختید را ایمپورت کنید:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { WebSocketModule } from './websocket/websocket.module';
@Module({
imports: [WebSocketModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
فایل websocket.service.ts
، فایل اصلی است که وطیفه اش ساختن gateway است:
import { ConnectedSocket, MessageBody, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway()
export class WebSocketService implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
private readonly logger = new Logger(WebSocketService.name);
constructor() {
console.log('WebSocketService initialized');
}
afterInit(server: Server) {
console.log('Initialized');
}
handleConnection(client: Socket) {
console.log(`Client connected: ${client.id}`);
// Handle connection event
}
handleDisconnect(client: Socket) {
console.log(`Client disconnected: ${client.id}`);
// Handle disconnection event
}
@SubscribeMessage('chat_message')
handleMessage(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
console.log(`Received message from ${client.id}: ${data}`);
// Handle received message
this.server.emit('chat_message', data); // Broadcast the message to all connected clients
}
@SubscribeMessage('joinChatRoom')
handlejoinChatRoom(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
console.log(`joinChatRoom with id : ${data}`);
this.server.emit('joinChatRoom', data);
}
@SubscribeMessage('leftChatRoom')
handleLeftChatRoom(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
this.server.emit('leftChatRoom', data);
}
@SubscribeMessage('events')
handleEvent(@MessageBody() data: string): string {
return data;
}
}
*SubscribeMessage('joinChatRoom')
مشخص می کند پیامی که ارسال و دریافت می شود با چه آیدی است (joinChatRoom
) . در سمت فرانت هم باید با همین آیدی پیامتان را ارسال و دریافت کنید.
* this.server.emit('leftChatRoom', data);
پیام را به تمامی client هایی که به این gateway هستند ارسال می کند.
سمت client
سمت فرانت ، مثلا جایی که کاربر صفحه چت را باز می کند، یک useEffect
بنویسید که اتصال websocket را برقرار کند و به event ها (یا همان پیامها) که می آید گوش دهد. با تابع emit
هم می توانید به gateway داده ارسال کنید:
*یادتان باشد که وقتی صفحه چت بسته شد، حتما socket را ببندید.
useEffect( () => {
const initializeSocket = async () =>
{
const socket = io('ws://localhost:5000', { transports: ['websocket'] });
socket.on('chat_message', async (chat_message) => {
console.log("chat_message",chat_message);
});
socket.on('joinChatRoom', async (joinChatRoom) => {
console.log("socket joinChatRoom",joinChatRoom);
});
socket.on('leftChatRoom', async (leftChatRoom) => {
console.log("socket leftChatRoom",leftChatRoom);
});
socket.on('connect', () => {
console.log('Connected to WebSocket');
});
socket.on('disconnect', () => {
console.log('Disconnected from WebSocket');
});
}
return () => {
socket?.emit("leftChatRoom",{user_id:onlineUser._id})
socket?.disconnect(); // Disconnect when the component unmounts
};
}, [messageDialog]);
* ws://localhost:5000
آدرس پورت سرور است که gateway را روی آن بالا آوردید. اگر از https استفاده می کنید به جای ws
از wss
استفاده کنید.
*هر جایی از برنامه ، مثلا وقتی کاربر پیامی جدید ارسال کرد، می توانید به gateway هم ارسال کنید:
socket.emit('chat_message', data );
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین ویرایش 1 سال قبل
- شما باید برای ارسال دیدگاه وارد شوید