我用python-socketio和socket.io-client实现了一个网站聊天。
有时候,当我们在不同的浏览器中同时打开多个标签,或者与同一个登录用户进行匿名会话时,新打开的标签可以成功地发送和接收消息。但是,旧的标签可以发送但不能接收消息,即使它们仍然连接到Python Socket.IO和socket.io-client。此外,我已经使用了一个房间会话来管理连接。这个问题发生在一个实时服务器上,在任何时候都有大约50-100个用户连接到套接字,而不是在本地主机上。
我使用的版本如下:
python-socketio==5.9.0
uvicorn==0.16.0
eventlet==0.33.3
socket.io-client = 4.7.2
字符串
后台:
import socketio
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins='*', logger=True, engineio_logger=True)
connected_users = {}
room_user_count = {}
@sio.on("connect")
async def connect(sid, environ):
try:
query_string = environ.get("QUERY_STRING") or "Anonymous"
if query_string:
username = query_string.split("username=")[1].split("&")[0]
await sio.save_session(sid, {'username': username})
room_name = await change_group_name(username)
sio.enter_room(sid, room_name)
print(f"[Connected] {sid}")
except Exception as e:
print("Connected error", str(e))
@sio.on("login")
async def handle_login(sid, data):
username = data.get("username")
session_id = await sio.get_session(sid)
connected_users[sid] = {"username": username, "session_id": session_id['username']}
print(f"{username} logged in.")
@sio.on("disconnect")
async def disconnect(sid):
try:
username = connected_users.get(sid, {}).get("username", "Anonymous")
connected_users.pop(sid, None)
leave_room = await change_group_name(username)
sio.leave_room(sid, leave_room)
print(f"Disconnected: {sid}, Username: {username}")
except Exception as e:
print(f"Disconnected Error: {e}")
@sio.on("client_chat_app")
async def message_from_client(sid, data):
username = connected_users.get(sid, {}).get("username", "Anonymous")
user = await get_user_obj(username)
await chat_app_function(data, user, sid)
型
前端:
import socketIOClient from "socket.io-client";
useEffect(() => {
let username = “username”;
socket = socketIOClient(WEB_SOCKET_IO, {
query: { username: username },
secure: true,
transports: ["websocket"],
path: "/socket.io/",
reconnectionDelay: 1000,
reconnection: true,
reconnectionAttempts: Infinity,
});
socket.on("connect", () => {
socket.emit("login", { username });
});
let event_chat_app = username + "sent_chat_app";
socket.on(event_chat_app, (value) => {
try {
console.log(“value”, value)
} catch (e) {}
});
}
return () => {
socket?.disconnect();
};
}, []);
型
我可以做些什么来确保同步问题不再发生?
2条答案
按热度按时间nhhxz33t1#
如果旧标签可以发送消息但不能接收消息,则可能是服务器内的消息分发存在问题。以下是有关此问题的几个选项:
**1.检查消息广播逻辑:**检查您的
chat_app_function
,确保它正确地广播消息到用户的房间。确保它使用sio.emit或类似的方法将消息发送到相应的房间,并且不存在导致消息被跳过的条件。**2.验证房间成员身份:**请再次确认较旧的页签是否为正确房间的成员。您可以记录特定SID的房间成员身份,以确保它们位于发送消息的房间中。
**3.重连事件处理:**标签页重连时,确保标签页正确的重新建立连接并重新加入房间,需要有重连事件和房间加入的处理逻辑。示例:
字符串
**4.考虑实现确认:**在消息发送过程中实现确认,可以帮助您确认客户端是否收到消息,客户端可以确认收到,服务器端可以确认未收到,保证消息传递的可靠性。
这些建议应该能有效地解决这个问题,确保旧的标签页能按预期收到消息。如果这些建议对你的情况有帮助,请告诉我。
nzk0hqpo2#
问题是
client_manager
丢失了。我不得不将AsyncRedisManager
添加到AsyncServer
。使用消息代理:实现一个像Redis,RabbitMQ或Kafka这样的消息代理来管理多个worker之间的消息和事件同步。当用户发送消息或事件时,它可以发布到消息代理,所有worker都可以订阅它以接收更新。换句话说,
room1
和room1
对于两个不同的用户可能是不同的。修复它的代码如下:
字符串
我还需要使用
pip3 install aioredis
来完成这项工作。