flaskweb——实时通讯聊天服务项目推送通知功能的实现(代码片段)

胖虎是只mao 胖虎是只mao     2022-12-14     555

关键词:

一、聊天服务实现

在toutiao-backend/im目录中创建server.py

import socketio

# 创建sio对象
sio = socketio.Server(async_mode='eventlet')
app = socketio.Middleware(sio)

在toutiao-backend/im目录中创建im服务启动程序main.py

运行方式python main.py [端口],如python main.py 8000

import eventlet
eventlet.monkey_patch()

import eventlet.wsgi
import sys


# 通过sys模块 获取启动命令中的参数  sys.argv
# # python main.py 8001 ...
# sys.argv -> ['main.py', '8001', ...]
# 获取命令行参数,目的是想让im服务运行的端口在启动程序时指定
if len(sys.argv) < 2:
	 # 表示启动时忘了传递端口号参数
    print('Usage: python main.py [port]')
    exit(1)		 # 表示程序异常退出

port = int(sys.argv[1])

# 通过导入事件处理模块的方法,让主程序知道事件处理方法的存在
from server import app
import notify

# socketio服务器运行的地址
SERVER_ADDRESS = ('', port)

# 创建协程服务器 并启动
# SERVER_ADDRESS = ('', 8000)

# 需求 想要将端口不写死在程序代码中,想要在启动的时候执行端口号
# python server.py [port]
# python server.py 8001
# 启动socketio服务器
sock = eventlet.listen(SERVER_ADDRESS)
eventlet.wsgi.server(sock, app)

在toutiao-backend/im目录中创建chat.py

from server import sio
import time


# 跟客户端的约定,
# 对于聊天场景,通讯时使用message事件
# 在聊天的通讯中,传输的聊天数据约定格式
# 
#     "msg": "",
#     "timestamp": 发送或接受消息的时间戳
# 



@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事件消息时执行
    """
    """
    客户端向服务器发送聊天的事件消息时 被调用
    :param sid:
    :param data:
    :return:
    """
    # 获取用户说的信息 data

    # TODO 使用rpc 调用聊天机器人子系统 获取回复内容
    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)

使用firecamp.app进行测试

二、在线消息推送实现

需求

在头条的Flask应用中,用户关注后需要推送消息,通过消息队列告知IM服务为用户进行推送

Socker.io 代替了celery,详细可看生产者消费者模式

在Socket.IO 框架中可以选择使用以下两种方式作为消息中间件:

  • 使用Redis

      mgr = socketio.RedisManager('redis://')
      sio = socketio.Server(client_manager=mgr)
    
  • 使用RabbitMQ

      pip install kombu
      mgr = socketio.KombuManager('amqp://')
      sio = socketio.Server(client_manager=mgr)
    

实现

因为要给指定的用户推送消息,所以需要用到用户的身份,用户在客户端携带JWT连接SocketIO服务器,我们在服务器端对jwt token进行验证,对于验证出用户身份(user_id)的客户端,将其添加到名为用户id的room房间中,方便按照user_id进行推送。

socketio服务端编写

在toutiao-backend/im/main.py中补充添加搜寻包的路径,方便使用utils中的jwt_utils模块

import eventlet
eventlet.monkey_patch()

import eventlet.wsgi
import sys
import os

# 补充搜索包路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'common'))

if len(sys.argv) < 2:
    print('Usage: python main.py [port]')
    exit(1)

port = int(sys.argv[1])

from server import app
import chat
import notify

SERVER_ADDRESS = ('', port)
sock = eventlet.listen(SERVER_ADDRESS)
eventlet.wsgi.server(sock, app)

在toutiao-backend/im/server.py文件中补充消息队列rabbitmq的配置信息和jwt使用的秘钥

import socketio

RABBITMQ = 'amqp://python:rabbitmqpwd@localhost:5672/toutiao'
JWT_SECRET = 'TPmi4aLWRbyVq8zu9v82dWYW17/z+UvRnYTt4P6fAXA'

mgr = socketio.KombuManager(RABBITMQ)

sio = socketio.Server(async_mode='eventlet', client_manager=mgr)
app = socketio.Middleware(sio)

在toutiao-backend/im目录中新建notify.py

from server import sio, JWT_SECRET
from werkzeug.wrappers import Request
from utils.jwt_util import verify_jwt

def check_jwt_token(environ):
    """
    检验jwt token
    :param environ:
    :return:
    借助werkzeug提供的Request类,将environ字典转换为我们熟悉的request对象,从对象中读取属性的方式来获取客户端的请求信息
    request = Request(environ)  # 等价于flask 的request对象

    """
    request = Request(environ)
    
    # 从查询字符串中取出jwt token
    token = request.args.get('token')
    if token:
        payload = verify_jwt(token, JWT_SECRET)
        if payload:
            user_id = payload.get('user_id')
            return user_id
    return None

@sio.on('connect')
def on_connect(sid, environ):
    """
    与客户端建立连接后执行
     当客户连接时被执行
    :param sid:
    :param environ: dict 解析客户端握手的http数据
    :return:
    """
    # 检验连接客户端的jwt token
    user_id = check_jwt_token(environ)
    print('user_id='.format(user_id))
    # 若检验出user_id,将此客户端添加到user_id的room中
    if user_id:
        sio.enter_room(sid, str(user_id))

@sio.on('disconnect')
def on_disconnect(sid):
    """
    与客户端断开连接时执行
    """
    # 客户端离线时将客户端从所有房间中移除,不再推送
    rooms = sio.rooms(sid)
    for room in rooms:
        sio.leave_room(sid, room)

socket.io 主动向客户端推送,不需要写推送方法

flask web服务端编写

toutiao-backend/toutiao/__init__.py中 添加sio对象的创建

import socketio

def create_app(config, enable_config_file=False):
    """
    创建应用
    :param config: 配置信息对象
    :param enable_config_file: 是否允许运行环境中的配置文件覆盖已加载的配置信息
    :return: 应用
    """
    ...

    # socket.io
    # 通过sio mgr对象 可以发布要进行及时消息推送的任务,由socketio服务器从rabbitmq中取出任务,推送消息
    app.sio = socketio.KombuManager(app.config['RABBITMQ'], write_only=True)
    #  write_only=True  仅仅发布,不会从队列中取
    

    ...

然后,可以在视图中发布任务

在toutiao-backend/toutiao/resources/user/following.py 用户关注接口视图中添加发送事件消息

class FollowingListResource(Resource):
    """
    关注用户
    """
    method_decorators = 
        'post': [login_required],
        'get': [login_required],
    

    def post(self):
        """
        关注用户
        """
        # 关注用户的数据库保存
        ...

        # 发送关注通知
        _user = cache_user.UserProfileCache(g.user_id).get()
        _data = 
            'user_id': g.user_id,
            'user_name': _user['name'],
            'user_photo': _user['photo'],
            'timestamp': int(time.time())
        
        '''
        通过socketio提供的kombu管理对象 向rabbitmq中写入数据,记录需要由socketio服务器向客户端推送消息的任务
		这里不是socket.io通讯,只是向mq中写入数据
		'''

        current_app.sio.emit('following notify', data=_data, room=str(target))

        return 'target': target, 201

效果:

用于实现实时聊天应用程序的推送通知与 Web 套接字?

】用于实现实时聊天应用程序的推送通知与Web套接字?【英文标题】:PushNotificationvs.WebSocketsforimplementingareal-timechatapp?【发布时间】:2014-05-0908:04:24【问题描述】:我正在考虑为iPhone构建一个实时聊天应用程序(但这个问题也适... 查看详情

聊天应用程序的 Firebase 推送通知

...时间】:2018-11-1404:38:36【问题描述】:我正在使用Firebase实时数据库开发一个聊天应用。我已经能够正确发送和接收消息。现在,我想在收到新消息时实现通知。即,每当任何用户发送消息时,推送通知都会在其他拥有该应用程... 查看详情

在聊天应用程序中实现推送通知

...时间】:2021-08-2612:51:42【问题描述】:我正在使用firebase实时数据库构建一个聊天功能,其中一个整数变量存储一个数字(在线整数),当人A打开聊天时,它会将1添加到数据库中,然后如果另一个人B上线并打开聊天然后它添加... 查看详情

im即时通讯开发:百万人的直播实时聊天消息分发技术

...大用户量的直播间场景已然常态化。大用户量直播间中的实时互动是非常频繁的,具体体现在技术上就是各种用户聊天、弹幕、礼物、点赞、禁言、系统通知等实时消息如此大量的实时消息,在分发时如何处理才能不至于把服务... 查看详情

来自服务器的 iPhone 实时通知,无需使用 Apple 推送通知

】来自服务器的iPhone实时通知,无需使用Apple推送通知【英文标题】:iPhonerealtimenotificationfromaserver,withoutusingApplepushnotification【发布时间】:2009-10-1916:48:54【问题描述】:我正在寻找一种从iPhone应用程序中的服务器获取实时通知... 查看详情

即时通讯开发长连接网关技术:websocket实时推送网关技术

...(IM中最为常见,比如IM的离线消息推送)、实时通知等应用场景,需要实时将数据同步到客户端&# 查看详情

如何使用 quickblox 实时获取推送通知

】如何使用quickblox实时获取推送通知【英文标题】:Howgetpushnotificationinrealtimewithquickblox【发布时间】:2015-08-1020:02:45【问题描述】:我在使用quickblox推送通知服务时遇到问题:有时推送通知会实时到达我的用户,有时需要很长时... 查看详情

实现ios端即时通讯开发的高性能消息推送

...,通常在以下场景下非常有用:   1)IM即时通讯聊天应用:聊天消息通知、音视频聊天呼叫等;   2)新闻资讯应用:最新资讯通知等, 查看详情

如何在firebase中处理推送通知

...10:49:19【问题描述】:我正在使用firebase和phonegap开发一个实时聊天应用程序,我需要在应用程序未运行时处理推送通知。请指导我在我的后端服务器上处理推送通知以进行firebase更改。谢谢【问题讨论】:这个问题太笼统了。请... 查看详情

应用服务性能

...我正在开发一个分布式系统应用程序,除此之外,它使用实时消息来聊天服务并将通知推送到许多并发用户通知。首先,我的实际项目系统是一个SpringFrameworkWebservices和另外两个服务器,一个用于实时消息传递服务,另一个用于... 查看详情

ios上的实时推送通知教程

】ios上的实时推送通知教程【英文标题】:Livepushnotificationtutorialonios【发布时间】:2012-08-1309:42:33【问题描述】:我已经尝试了很多教程来为我的应用程序发送推送通知服务。当我在设备上测试它时它可以工作。但是如果我在我... 查看详情

ejabberd 和推送通知

...述】:我已经使用XMPP在我的iOS和Android应用程序中集成了聊天系统。我在服务器端使用了ejabberd2。聊天系统工作正常。我想使用APNS和GCM在我的聊天中集成推送通知。如何在每条聊天消息中发送推送通知?ejabberd2有任何API或扩展可... 查看详情

苹果推送通知问题

...描述】:我是苹果推送通知的新手。我目前正在开发具有聊天功能的ios应用程序。对于这个应用程序,Web服务是用PHP构建的。有一个功能,当用户向另一个用户发送聊天消息时,我们会通过PHP该Web服务向消息接收者用户发送推送... 查看详情

来自 UrbanAirship 的推送通知不适用于 android 中的实时服务器(即使用生产密钥)

】来自UrbanAirship的推送通知不适用于android中的实时服务器(即使用生产密钥)【英文标题】:pushnotificationfromUrbanAirshipnotworkingwithliveserver(i.e.withproductionkey)inandroid【发布时间】:2011-12-2310:20:15【问题描述】:在我的一个Android应用... 查看详情

socket.io入门,简易聊天室(代码片段)

...属于服务器推送技术的一种。Socket.IO是一个基于Node.js的实时应用程序框架,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用。socket.io包含两个部分:服务器端(server):运行在Node.js服务器上客户端(client)... 查看详情

使用推送通知进行实时更新有啥问题?

】使用推送通知进行实时更新有啥问题?【英文标题】:Whatarethegotchasofusingpushnotificationsforrealtimeupdates?使用推送通知进行实时更新有什么问题?【发布时间】:2021-03-1903:33:45【问题描述】:我们有一个react-native应用程序,并希望... 查看详情

浅析即时通讯开发实时信息推送服务器ddpush

IM(InstantMessaging)即时通讯系统,从1996年ICQ的出现,到国际巨头割据的今天,已经深刻地影响了互联网,甚至人类社会的变化。从移动互联网时代开始,即时通讯系统更是加剧演变进化,除了iOS和Android提供... 查看详情

聊天功能插件socket.io(代码片段)

一、Socket.io是什么  是基于时间的实时双向通讯库  基于websocket协议的  前后端通过时间进行双向通讯  配合express快速开发实时应用二、Socket.io和ajax区别  基于不同的网络协议  ajax基于http协议,单向,实时获取... 查看详情