支持一对一的私聊模式,而不是聊天室形式。
from flask import Flask, request, session
from flask_socketio import SocketIO, emit, join_room, leave_room
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
socketio = SocketIO(app)
# 用来存储私聊消息历史记录
messages = {}
# 用来存储用户会话和对应的私聊会话号
sessions = {}
@app.route('/history', methods=['GET'])
def history():
"""
获取与指定用户的私聊历史记录
"""
username = request.args.get('username')
room = sessions.get((session.get('username'), username))
if room and messages.get(room):
return {'messages': messages[room]}
return {'messages': []}
@socketio.on('join')
def join(data):
"""
建立一对一私聊会话
"""
username = data['username']
peer = data['peer']
room = (username, peer)
join_room(room)
# 存储会话和私聊会话号的对应关系
sessions[(session['username'], peer)] = room
# 如果之前有历史记录,发送给用户
if messages.get(room):
emit('history', {'messages': messages[room]}, room=request.sid)
@socketio.on('message')
def message(data):
"""
接收和发送新消息
"""
sender = session.get('username')
recipient = data['recipient']
content = data['content']
room = sessions.get((sender, recipient))
# 存储新消息
if messages.get(room):
messages[room].append((sender, content))
else:
messages[room] = [(sender, content)]
# 发送给接收者
emit('message', {'sender': sender, 'content': content}, room=room)
@socketio.on('leave')
def leave(data):
"""
结束私聊会话
"""
username = data['username']
peer = data['peer']
room = sessions.get((session.get('username'), peer))
leave_room(room)
sessions.pop((session.get('username'), peer))
if __name__ == '__main__':
socketio.run(app, debug=True)
使用说明:
1.运行该Flask应用后,客户端需要先向/history?username=xx接口发送GET请求获取与指定用户的私聊历史记录。
2.客户端连接到Socket.IO服务器,并使用emit('join', {'username': xx, 'peer': xx})建立一对一私聊会话。
3.发送新消息使用emit('message', {'recipient': xx, 'content': xx})。
4.结束私聊会话使用emit('leave', {'username': xx, 'peer': xx})。
5.该demo使用session存储当前用户名,私聊会话号是一个包含发送者和接收者用户名的元组。
6.所有私聊消息按会话号存储在内存中的字典messages,实际可以存储在数据库中。消息记录包含发送者和内容。
7.接收消息时,服务器会向对应的私聊会话号广播消息,只有发送者和接收者能收到。
这个demo实现了一对一私聊的基本功能,你可以根据实际需求继续扩展,比如添加在线状态查看、未读消息计数等功能。