python基于flask_socketsio实现WebSocket——肆

Flask-SocketsFlask-SocketIO区别

Flask-SocketsFlask-SocketIO之间的主要区别在于前者仅仅将WebSocket协议(通过使用gevent-websocket项目)进行包装,因此它只适用于原生支持WebSocket协议的浏览器,对于那些不支持WebSocket协议的较老的浏览器,就无法使用它了。 Flask-SocketIO则不同,通过前面的介绍,读者应该已经知道了它不仅实现了WebSocket协议,并且对于那些不支持WebSocket协议的旧版浏览器,使用它也能够实现相同的效果。新版旧版的浏览器都能使用他 ,另一个区别是Flask-SocketIO实现了SocketIO Javascript库公开的消息传递协议。 Flask-Sockets只是实现通信通道,发送的是完全取决于应用程序。 
Flask-SocketIO还为事件处理程序创建了一个类似flask的常规视图函数的环境,包括创建应用程序和请求上下文。 然而,在文档中会介绍一些重要的例外情形。

基于Flask-socketsio实现websocket服务端

#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: 415900617@qq.com
@software: PyCharm
@file: flask_websocket_server.py
@time: 2019/2/20 17:24
@describe: 基于flask_socketio实现websocket的服务端
同时借助flask的路由实现任务发布调度与 消息接收
"""
import sys
import os
from flask import Flask, request, render_template
from flask_socketio import SocketIO, emit
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")


app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
name_space = '/test'             # 命名空间
event_name = 'callback message'  # 消息接收对象
client_query = []


@app.route('/')
def index():
    """加载HTML客户端"""
    return render_template('index.html')


@app.route('/push')
def push_once():
    """
    客户端发送消息:http://127.0.0.1:5000/push?msg=a
    此方式发布消息见最后一篇代码
    """
    data = request.args.get("msg")
    broadcasted_data = {'data': data}
    print('send msg==>', broadcasted_data)
    print("clicent_query==>", client_query)
    """
    指定客户端方式发送消息,如果需要针对某一客户端发送,则添加room参数: room=client_query[0],
    这里指定第一个连接客户端
    emit(event_name, broadcasted_data, broadcast=False, namespace=name_space, room=client_query[0])
    """

    # 广播方式发送消息
    emit(event_name, broadcasted_data, broadcast=True, namespace=name_space)
    return 'send msg ok!'


# on('消息订阅对象', '命名空间区分')
@socketio.on('message', namespace=name_space)
def test_message(message):
    """ 服务端接收消息 """
    print('recevice message', message)
    # 回传给客户端消息,也可以选择不回传
    emit('callback message', {'data': message}, broadcast=True, namespace=name_space)


@socketio.on('my broadcast event', namespace=name_space)
def test_message_2(message):
    print("my response===>", message)
    emit('my response', {'data': message}, broadcast=True)


@socketio.on('connect', namespace=name_space)
def test_connect():
    # 建立连接 sid:连接对象ID
    client_id = request.sid
    print('1 connected ==> ', client_id)
    client_query.append(client_id)
    emit('connect', '%s connect successful!' % client_id, broadcast=True)


@socketio.on('disconnect', namespace=name_space)
def test_disconnect():
    # 连接对象关闭 删除对象ID
    client_query.remove(request.sid)
    print('0 Client disconnected==> ', request.sid)


if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5000, debug=True)

模板文件,需要放到与服务端同级目录templates/index.html

 需要在控制台查看返回消息

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            namespace = '/test';
            var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
       //连接后发送日志
            socket.on('connect', function(msg){
              console.log('connected');
              console.log(msg);
            });
       //点击发送时将text框的内容发送到后端
            $('form#emit').submit(function(event) {
                socket.emit('message', {data: $('#emit_data').val()});
                socket.on('callback message', function(msg) {
                    console.log(msg.data);
                });
                socket.emit('my broadcast event', {data: $('#emit_data').val()});
                    socket.on('my response', function(msg) {
                    console.log(msg.data);
                    });
                return false;
            });
        //接收后端广播的信息

            socket.on('my response', function(msg) {
            console.log(msg);
            });

        });
    </script>
</head>
<body>
  <form id="emit" method="POST" action='#'>
      <input type="text" name="emit_data" id="emit_data" placeholder="Message">
      <input type="submit" value="发送">
  </form>
  <h2>Receive:</h2>
  <div id="log"></div>
</body>
</html>

python socketio模块发布消息与接收消息

#!/usr/bin/env python  
# encoding: utf-8  
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence  
@contact: 415900617@qq.com 
@software: PyCharm 
@file: test_clicent.py 
@time: 2019/2/21 10:31 
@describe: 采用 socketio 模块进行消息发布与接收
https://python-socketio.readthedocs.io/en/latest/server.html
"""
import sys
import os
import socketio
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")

name_space = '/test'
sio = socketio.Client()


@sio.on('connect')
def on_connect():
    """创建连接"""
    print('I am connected!')


@sio.on('my message')
def on_message(data):
    print('I received a custom message!')


@sio.on('disconnect')
def on_disconnect():
    """关闭连接"""
    print('I m disconnected!')

'''
官方文档:
    事件回调:
        当客户端向服务器发送事件时,它可以选择提供回调函数,作为服务器处理事件的确认方式调用。
        虽然这完全由客户端管理,但服务器可以提供要传递给回调函数的值列表,只需从处理函数返回它们:
        @sio.on('my event', namespace='/chat')
        def my_event_handler(sid, data):
            # handle the message
            return "OK", 123
        同样,服务器可以请求在客户端处理事件后调用回调函数。该socketio.Server.emit()
        方法有一个可选callback参数,可以设置为可调用。如果给出了此参数,则在客户端处理完事件后将调用callable,
        并且客户端返回的任何值都将作为参数传递给此函数。不建议在向多个客户端广播时使用回调函数,
        因为将为接收消息的每个客户端调用一次回调函数。
'''

@sio.on('callback message', namespace=name_space)
def my_event_handler(data):
    # 客户端接收服务端的回调消息
    print("my receive new msg:", data)
    # 接收完消息关闭连接
    sio.disconnect()
    return "ok!"


# 建立连接对象
sio.connect('http://127.0.0.1:5000')
sio.emit('message', {'test': 'i am test msg!'}, namespace=name_space)

python 调用服务端发布命令,直接只发送不接受消息模式

基于flask,flask_socketio

#!/usr/bin/env python  
# encoding: utf-8  
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence  
@contact: 415900617@qq.com 
@software: PyCharm 
@file: clicentMqtt.py
@time: 2019/1/4 11:25 
@describe: 发送查询消息请求
"""
import sys
import os
import requests
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")


def clicent_main(msg):
    """
    发布消息
        --基于requests客户端单发给服务端,并不接受服务端回传消息
        --http://127.0.0.1:5000/push?msg=a
    """
    print('0==> send msg: ', msg)
    try:
        ws = requests.get("http://127.0.0.1:5000/push?msg=%s" % (msg), timeout=5)
        print(ws.text)
    except Exception as e:
        print(e)


if __name__ == '__main__':
    data = {'data': "i am test msg!"}
    clicent_main(data)

 

上一篇:linux项目实战---lamp架构(十一)Zabbix云报警、API调用及数据迁移


下一篇:JsonRPC 入门