Socket.IO

2016/05/27 Socket.IO 阅读次数: socket socketio

Socket 便利不用多说,python 支持原生socket tcp,udp;原生没有封装好的方法,都需要自己手动去实现,尤其是心跳; 基于socket,衍生出了多个三方包,WebSocket,socketio,flask-socketio,django-socketio,这里介绍flask-socketio和socketio

flask-socketio

1 flask_socketio是基于flask框架封装的一个包,如果只是搭建服务端,真的好用;前端请求,数据可以实时传输,长连接

```shell script pip flask-socketio

#### 2 服务端   
```python
# coding=utf-8
import logging
import random
from threading import Lock

from . import api
from app import socketio,SocketIO
from flask_socketio import emit # 发送信息
from flask import request, jsonify, current_app, session,render_template

thread = None
thread_lock = Lock()

def background_thread(users_to_json):
    """Example of how to send server generated events to clients."""
    while True:
        users_to_json = [{'name': '王腾' + str(random.randint(1, 100))}]
        socketio.sleep(5) # 每五秒发送一次
        logging.info(users_to_json)
        socketio.emit('user_response', {'data': users_to_json}, namespace='/websocket/user_refresh')

@socketio.on('connect',namespace='/websocket/user_refresh')
def connect():
    """服务端自动发送请求"""
    global thread
    user_to_json = ''
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(background_thread, (user_to_json,))

    logging.info("----客户端连接---------")
    emit('server_response', {'data': '试图连接客户端!'})


@socketio.on("connect_event",namespace='/websocket/user_refresh')
def refresh_message(message):
    """服务端接收客户端消息"""
    logging.info("----------"+message["data"])
    emit('server_response', {'data': message['data']})



@socketio.on("disconnect",namespace="/websocket/disconnect")
def disconnect():
    logging.error('Client disconnected')



@api.route('/', methods=['GET'])
def index():
    return render_template('index.html')

由于采用了manager,连接是放在__init__中了,目录结构如下


3 客户端 js

<script src="/static/js/jquery.slim.js"></script>
<!-- 新添加代码  start -->
    <script src="/static/js/socket.io.dev.js"></script>
    <script>
        // 后台接口
        var socket = io('http://127.0.0.1:8080/websocket/user_refresh');
        socket.on('connect', function() { // 发送到服务器的通信内容
        socket.emit('connect_event', {data: '我已连接上服务端!'});
        });

        socket.on('server_response', function(msg) {
            //显示接受到的通信内容,包括服务器端直接发送的内容和反馈给客户端的内容
            console.log(msg);
        });

        socket.on('user_response', function(msg) {
            // 获取后端传过来的业务数据
            var obj = eval(msg.data[0]);
            console.log(obj);
            $("#auto_num").empty();
            $("#auto_num").append(obj['name']);

        });
    </script>
  • 如果要是使用socket在后端实现客户端和服务端,原生socket很容易;如果服务端采用flask_socketio,客户端是没有如果服务端采用flask_socketio,如果采用socketIO_client你会发现,发送的接收不到, 客户端也不能收到服务端发送的消息,也不报错;换了websocket还是不行,网上说不配套,也有网友说都不维护了,在github上找到了socketio; socketio是分客户端和服务端,所以很好的能配套在一起使用.

python-socketio

python-socketio →

1 安装python-socketio

```shell script pip install python-socketio

pip install “python-socketio[client]”


#### 2 服务端  
```python
import socketio
from flask import Flask

sio = socketio.Server(async_mode='threading')
app = Flask(__name__)
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)


@sio.event
def my_event(sid, data):
    print(sid, data)

@sio.on('my custom event')
def another_event(sid, data):
    print(sid,data)

@sio.event
def connect(sid, environ):
    print('connect ', sid, environ)
    # 服务端在向客户端发送消息的时候,事件名称一定要一样 
    sio.emit('my message', {'data': 'foobar'})
    # 客户端 my event,是收不到的
    sio.emit('my event', {'data': 'foobar'})
    print("-------------------------------")

@sio.event
def disconnect(sid):
    print('disconnect ', sid)


if __name__ == '__main__':
    app.run(host="0.0.0.0",port=8080,threaded=True)

3 客户端


import socketio
import json
sio = socketio.Client()


@sio.event
def message(data):
    # message 是保留默认参数
    print(data)
    print('I received a message!')


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


@sio.event
def connect():
    # emit 第一个是事件,要和服务端的事件名称一致,不然收不到 
    sio.emit('my_event', {"data": "200"})
    print("I'm connected!")
    print('my sid is', sio.sid)


@sio.event
def connect_error():
    print("The connection failed!")


@sio.event
def disconnect():
    print("I'm disconnected!")


@sio.event
def my_event(sid, data):
    # handle the message
    print(data)
    return "OK", 123


sio.connect('http://127.0.0.1:8080')

sio.wait()

效果图如下

Search

    Table of Contents