Socket.IO Private and Group Messaging
1:1 private message, group message, typing indicator ও read receipt — বাংলায় পূর্ণ গাইড।
Chat application-এ দুই ধরনের messaging দরকার — 1:1 private message এবং group message। দুটোই আসলে room-ভিত্তিক।
শেখার লক্ষ্য
- private message (room-per-user) কীভাবে তৈরি হয়
- group message (room-per-group) তৈরি
- typing indicator
- delivered/read receipt ack দিয়ে
পদ্ধতি: প্রত্যেক User-এর নিজের Room
সবচেয়ে পরিচ্ছন্ন উপায় — connect-এর সময় প্রত্যেক socket-কে তার user id দিয়ে room-এ join করানো। এরপর কোন user-কে message পাঠাতে হলে io.to(userId).emit(...)।
io.on("connection", (socket) => {
// auth middleware user দিয়ে socket.data.user সেট করা আছে ধরা হলো
const userId = socket.data.user.id;
// নিজের user-room-এ join — private message receipt-এর জন্য
socket.join("user:" + userId);
console.log("online:", userId);
});// server — private message
socket.on("dm:send", ({ toUserId, text }) => {
// sender-এর user room-এ পাঠাই যাতে সব device-এ পৌঁছায়
io.to("user:" + toUserId).emit("dm:receive", {
from: socket.data.user.id,
text,
at: Date.now(),
});
});একজন user একই account-এ ফোন ও ল্যাপটপে logged-in থাকতে পারে। কারণ message user-id room-এ (socket.id নয়) যায়, তাই সব device-এ পৌঁছায়। client থেকে userId-এর বদলে socket.id ব্যবহার করলে এই সুবিধা মিলবে না।
Client Side
// server থেকে userId আসে (login response)
const me = { id: 7 };
socket.emit("dm:send", {
toUserId: 42,
text: "তোমার project কেমন চলছে?",
});
socket.on("dm:receive", (msg) => {
console.log(msg.from, "থেকে:", msg.text);
});Group Messaging
Group হলো একটি room; সদস্যরা join করে, আর message socket.to(groupId)-এ যায়।
// group তৈরি / join
socket.on("group:join", (groupId) => {
socket.join("group:" + groupId);
socket.to("group:" + groupId).emit("group:member:joined", {
id: socket.data.user.id,
});
});
// group message
socket.on("group:message", ({ groupId, text }) => {
socket.to("group:" + groupId).emit("group:message", {
from: socket.data.user.id,
groupId,
text,
});
});socket.to(...) দিয়ে sender-এর বাইরে room-এর সবাই পায়। sender নিজের message local-এ render করে — ডুপ্লিকেট echo এড়ায়। বিস্তারিত Broadcasting Events।
Typing Indicator
// client — input-এ typing
input.addEventListener("input", () => {
socket.emit("typing", { to: 42 });
});
// server — নির্দিষ্ট user-কে pass through
socket.on("typing", ({ to }) => {
socket.to("user:" + to).emit("typing", {
from: socket.data.user.id,
});
});Read Receipt (Acknowledgement)
message পৌঁছেছে কিনা নিশ্চিত করতে ack-এর সাথে server থেকে স্বীকৃতি:
// server sends with ack
io.to("user:" + toUserId)
.timeout(5000)
.emit("dm:receive", payload, (err, responses) => {
if (err) {
console.log("delivery uncertain");
return;
}
console.log("delivered to", responses.length, "device(s)");
});timeout ও callback বিস্তারিত Acknowledgements and Timeouts-এ। মনে রাখবেন: delivery ack ≠ message read। Read receipt-এর জন্য client-এ message render হলে আলাদা dm:seen event পাঠাতে হবে।
সাধারণ ভুল ও সমাধান
socket.idদিয়ে private message — reconnect-এ id বদলায়; তাই user id ব্যবহার করুন- Group-এ leave না করা — বেরিয়ে গেলেও message আসে;
group:leaveevent যোগ করুন - Input sanitize না করা — XSS-এর জন্য ভিত্তি; text escape করুন (Best Practices দেখুন)
Practice Task
user:<id>room-পদ্ধতিতে দুই user-এর মধ্যে 1:1 message চালান- একটি group বানিয়ে join/leave + group message implement করুন
- Typing indicator যোগ করুন — server pass-through দিয়ে
সম্পর্কিত অধ্যায়: Rooms · Namespaces · Acknowledgements and Timeouts