即时通讯服务器
init文件内容
__all__ = ["chat", "main", "notify", "server"]
import os, sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from . import chat
from . import main
from . import notify
from . import server
chat文件内容,测试的使用用的文件,没什么用
from server import sio
import time
a = 5
@sio.on('connect')
def on_connect(sid, environ):
"""
与客户端建立好连接后被执行
"""
print('sid={}'.format(sid))
print('environ={}'.format(environ))
msg_data = {
'msg': 'hello',
'timestamp': round(time.time()*1000)
}
sio.emit('message', msg_data, room=sid)
@sio.on('message')
def on_message(sid, data):
"""
接收message事件消息时执行
"""
print('sid={} data={}'.format(sid, data))
msg_data = {
'msg': 'I have received your msg: {}'.format(data),
'timestamp': round(time.time()*1000)
}
sio.send(msg_data, room=sid)
# sio.emit('message', msg_data, room=sid)
main文件内容
# import sys
# sys.path.insert(0, "/home/tanzhihao/test_3dview_remote/im")
# sys.path.insert(0, "/home/tanzhihao/test_3dview_remote/utils")
# sys.path.append('/home/tanzhihao/test_3dview_remote/utils')
import os, sys
sys.path.append(os.path.dirname(os.path.abspath('/home/tanzhihao/test_3dview_remote/utils')))
import eventlet
eventlet.monkey_patch()
import socketio
import eventlet.wsgi
import sys
from server import app
# 获取命令行参数,目的是想让im服务运行的端口在启动程序时指定
if len(sys.argv) < 2:
print('Usage: python main.py [port]')
exit(1)
port = int(sys.argv[1])
# chat
import chat
import notify
# socketio服务器运行的地址
SERVER_ADDRESS = ('', port)
# 启动socketio服务器
sock = eventlet.listen(SERVER_ADDRESS)
eventlet.wsgi.server(sock, app)
notify文件内容
from server import sio
from werkzeug.wrappers import Request
from utils.jwt_util import verify_jwt
def check_jwt_token(token):
"""
检验jwt token
:param token:
:return:
"""
payload = verify_jwt(token)
if payload is None:
return None
else:
return payload.get('user_id')
@sio.on('connect')
def on_connect_notify(sid, environ):
"""
当客户连接时被执行
@param sid:
@param environ: dict 解析客户端握手的http数据
"""
print("打印environ的数据:".format(environ))
# 借助werkzeug提供的Request类,将environ字典转换为我们熟悉的request对象,从对象中读取属性的方式来获取客户端的请求信息
request = Request(environ) # 等价于flask 的request对象
# 从查询字符串中取出jwt token
tokenData = request.args.get('token')
# 验证jwt token
# 如果有效 取出了user_id 将用户添加到user_id的房间
user_id = check_jwt_token(tokenData)
print(type(user_id))
print("拿到了token值:{}".format(user_id))
if user_id is not None:
sio.enter_room(sid, str(user_id))
# sio.emit('message', {'data': '你已经成功连接'}, room=sid)
@sio.on('message')
def on_message(sid, data):
"""
接收message事件消息时执行
"""
msg_data = data
sio.send(msg_data, room=sid)
@sio.on('disconnect')
def on_disconnect(sid):
"""
当用户断开连接时被执行
:param sid:
:return:
"""
# 将用户从专属vip包房剔除
rooms = sio.rooms(sid)
for room in rooms:
sio.leave_room(sid, room)
server文件内容
import socketio
# config_engine = {
# 'AMQP_URI': "pyamqp://admin:admin@10.84.62.199/my_vhost"
# }
# RABBITMQ = 'amqp://python:rabbitmqpwd@localhost:5672/toutiao'
RABBITMQ = 'amqp://admin:admin@localhost:5672/vhost01'
#创建rabbitmq消息队列的管理对象
mgr = socketio.KombuManager(RABBITMQ)
# 创建sio对象
sio = socketio.Server(cors_allowed_origins="*",
client_manager=mgr,
async_mode='eventlet')
# app对象交给eventlet携程服务器使用对接
app = socketio.Middleware(sio)
flask初始化app时的设置
RABBITMQ = 'amqp://admin:admin@localhost:5672/vhost01'
# socket.io
# 通过sio mgr对象 可以发布要进行即使消息推送的任务,由socketio服务器从rabbitmq中取出任务,推送消息
app.sio_mgr = socketio.KombuManager(RABBITMQ, write_only=True)
具体推送逻辑:
用户登录后给返回一个token,你用cookie或者json数据也可以,把用户的唯一id标识存进去,等链接socketio的时候再把这个参数带过去。把用户加进这个房间。
flask方面需要推送消息的使用就往这个房间里推送消息就可以了
启动服务器的方式
python main.py 5005
提示
服务器用的socketio版本和前端用的版本要对应,对应版本网上查一下。不对应的话不能链接的。