【问题标题】:Socket.io one to one chatSocket.io 一对一聊天
【发布时间】:2021-11-11 09:16:39
【问题描述】:

根据文档,当我们将消息发送到特定的 socket.id 时,就会发生一对一的聊天。 例如

io.to(socket.id).emit("event","message")

这仅适用于同时连接两个用户的情况。 如果我们要在我们的应用程序中添加聊天功能,注册用户可以互相聊天(1-1)。什么是最佳解决方案。我已经使用 io.to(socket.id) 实现了聊天,但是当一个的用户离线 socket.id 不可用。

----------------------客户-------- -----------------------

function Chat() {
const [conversations, setConversations] = useState([]);
const [currentChat, setCurrentChat] = useState(null);
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState("");
const [arrivalMessage, setArrivalMessage] = useState(null);
const scrollRef = useRef();
const socket = useRef();
const client = isAuthenticated()

const clientId = isAuthenticated().client._id;
const token = isAuthenticated().client.token
console.log(clientId)



useEffect(() => {
    socket.current = io("ws://localhost:8900");
    socket.current.on("getMessage", (data) => {
      setArrivalMessage({
        sender: data.senderId,
        text: data.text,
        createdAt: Date.now(),
      });
    });
  }, []);



  useEffect(() => {
    arrivalMessage &&
      currentChat?.members.includes(arrivalMessage.sender) &&
      setMessages((prev) => [...prev, arrivalMessage]);
  }, [arrivalMessage, currentChat]);

  useEffect(() => {
    socket.current.emit("addUser",clientId );
  
  }, [client]);



useEffect(() => {
getconversation(clientId,token).then((data)=>{
    if(data.error){
        console.log(data.error)
    }else{
        console.log(data)
        setConversations(data)
        
    }
})
}, [])

useEffect(() => {
const getMessages = async () => {
  try {
    const res = await axios.get("http://localhost:8080/api/messages/" + currentChat?._id);
    setMessages(res.data);
  } catch (err) {
    console.log(err);
  }
};
getMessages();
  }, [currentChat]);


useEffect(() => {
    scrollRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

const handleSubmit = async (e) => {
    e.preventDefault();
    const message = {
      sender:clientId,
      text: newMessage,
      conversationId: currentChat._id,
    };

    const receiverId = currentChat.members.find(
      (member) => member !== clientId
    );

    socket.current.emit("sendMessage", {
      senderId: clientId,
      receiverId,
      text: newMessage,
    });

    try {
      const res = await axios.post("http://localhost:8080/api/messages", message);
      setMessages([...messages, res.data]);
      setNewMessage("");
    } catch (err) {
      console.log(err);
    }
  };

--------------服务器---------- --------------------

const io = require("socket.io")(8900, {
cors: {
  origin: "http://localhost:3000",
},
});

 let users = [];

 const addUser = (userId, socketId) => {
 !users.some((user) => user.userId === userId) &&
  users.push({ userId, socketId });
  };

  const removeUser = (socketId) => {
   users = users.filter((user) => user.socketId !== socketId);
   };

  const getUser = (userId) => {
    return users.find((user) => user.userId === userId);
    };

  io.on("connection", (socket) => {
    //when connect
    console.log("a user connected."+socket.id);


    //take userId and socketId from user
    socket.on("addUser", (userId) => {
  
      addUser(userId, socket.id);
      io.emit("getUsers", users);
      });

    //send and get message
    socket.on("sendMessage", ({ senderId, receiverId, text }) => {
    console.log("receiverid=====>>>",receiverId)
    console.log("users ",users)
    const user = getUser(receiverId);
    console.log("userSocket Id",user)
    io.to(user.socketId).emit("getMessage", {
    senderId,
    text,
     });
    });

//when disconnect
socket.on("disconnect", () => {
  console.log("a user disconnected!");
  removeUser(socket.id);
  io.emit("getUsers", users);
});
});

【问题讨论】:

    标签: node.js socket.io chat mern


    【解决方案1】:

    首先需要在您的应用中存储消息,以及发送者、接收者和时间戳的详细信息。然后使用 web sockets / socket.io 来补充功能并实时通知每个用户,如果他们在线。 这种方法是其他聊天应用所遵循的方法,例如 Slack。

    所以你的应用的主要属性应该是,

    1. 当用户发送消息时,客户端应将其发布到后端/服务器进行存储。
    2. 服务器应通过套接字发出消息。一旦您变得更大并拥有集群,这将通过发布-订阅服务等变得更加复杂。
    3. 在线用户会收到消息,并在聊天屏幕上呈现。
    4. 如果用户刷新或用户离线并返回,则将从服务器获取该用户的所有消息。

    关于发射部分,使用唯一标识符,例如在一个或多个用户之间生成的会话的唯一标识符 (uuid),以针对房间(用户应收听此标识符)或用户 ID 并发送给每个用户id(用户在线后可以收听自己的用户标识符)。消息的详细信息应该足以帮助应用在正确的屏幕上呈现它。

    【讨论】:

    • 我已将带有发送者和接收者 ID 的消息存储在我的数据库中。当用户 A 和用户 B 同时连接时,应用程序工作正常。当其中一个未连接时,我的套接字服务器找不到接收者的 socket.id 并崩溃..
    • @ShehryarTanoli 您可以在您自己的数据中通过套接字连接和断开连接(on('connection') 和 on('disconnect'))来维护连接的用户(或房间/组会话,如果您愿意)服务器内存中的结构,无需持久化。然后迭代并触发到您仍然发现连接的任何人。
    • @ShehryarTanoli 你试过使用 socket."emit" 吗?当 socket.emit('to something random',... 时我看不到任何错误
    • 让我编辑问题,我将分享我的代码,以便您查看。
    • 问题已更新
    猜你喜欢
    • 2019-04-01
    • 2018-12-30
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    相关资源
    最近更新 更多