跳转至

即时通讯-Socket.IO

Socket.IO

  • Socket.IO 主要使用WebSocket协议
  • !!! Socket.IO 不等价于 WebSocket,WebSocket只是Socket.IO实现即时通讯的其中一种技术依赖,而且Socket.IO还在实现WebSocket协议时做了一些调整
  • 如果又特殊需求,Socket.io可以回退到几种其它方法: Adobe Flash Sockets,JSONP拉取,AJAX拉取,提供了完全相同的接口
  • Socket.IO 会自动选择合适双向通信协议,我们用的时候了解套接字咋回事就OJ8K
  • 但是Socket.io并不是一个基本的,独立的,能够回退到其它实时协议的WebSocket库,支持标准WebSocket的服务端不能直接连接到Socket.io服务器,并且支持Socket.io的客户端也不能与非Socket.io框架的WebSocket服务器通信
  • Socket.io要求客户端与服务器端均须使用该框架
  • Socket.io的在通信时是串行执行,我们使用协程来实现异步执行,处理不同的客户端

Python实现

  • 客户端首发的请求,发送到eventlet,eventlet通过协程调用的方式找到socket.io 50036-kq8nq47sclh.png

安装

sudo pip install python-socketio
sudo pip install eventlet  # eventlet包提供了协程的支持

服务端实现

from eventlet import monkey_patch
monkey_patch()

import eventlet.wsgi
import socketio


# 创建服务器(指定异步执行模块)
sio = socketio.Server(asyne_mode = 'eventlet')


# 创建应用
app = socketio.Middleware(sio)


ip_port = ('', 8888) # 留空默认监听0.0.0.0


# 启动服务器
socket = eventlet.listen(ip_port)
eventlet.wsgi.server(socket, app)

事件

  • socket.io中没有路由的概念, 只有事件,所以我们需要监听事件,使用sio.on(event)装饰器的方式监听事件对应的处理函数(sio是服务器对象)
  • connect: 客户端一旦链接 im 服务器 就会触发, 会传进来两个参数:
  • sid: 每个客户端和服务点建立连接后会生成一个唯一的会话标识
  • environ: 一个字典结构,里面包含了三次握手之后,发送的一次wb协议握手携带的信息(url, 请求头,状态行......)
  • 重点 我们可以在三次握手之后发送wb协议的时候自定义一些请求信息(用户信息啥的),比如在headers中或者是QueryString
  • 因为发送wb协议的时候,时使用http1.1协议进行发送的
  • 在后台我们无法根据会话的sid得到是哪个用户链接的,不知道用户sid会话就无法给用户发送消息,所以可以要求前台在用户链接到im服务器的时候,在wb协议的的environ中把用户的信息传过来,这样把sid 和environ中的用户信息 暂时双向绑定
  • message: 监听客户端发过来的讯息,接收两个参数sid,,data其中data中包含了发送过来的数据
  • disconnect: 客户端在四次挥手结束触发,后只会传进来一个sid 30358-dhm8quotods.png

回复

  • emit: # 注意 这个默认是群发,只要连接到我们服务器上且监听了message时间的客户端都会收到
  • 发送消息给指定的客户端需要设置room参数,room就类似以前的聊天室
  • 如果设置 room=sid 则该回复只会发送到该sid对应的会话,其他的会话无法收到
  • 如果设置 room= room_id 那么只有进入该房间的会话才会收到消息
  • 可以使用sio.enter_room(sid, room = 'room_id')来让指定的用户进入房间
  • 使用sio.leave_room(sid, room = 'room_id')来让指定用户退出房间 76177-ejsq45pn8s.png

35546-t7j6r7bam6h.png

Demo

from eventlet import monkey_patch
import eventlet.wsgi
import socketio

monkey_patch() # 对下面的操作打补丁

# 创建服务器(指定异步执行模块)
sio = socketio.Server(asyne_mode = 'eventlet')

# 创建应用
app = socketio.Middleware(sio)


# 监听事件
@sio.on('connect')
def test_connect(sid, environ):
    print('{}, 建立了客户端链接'.format(sid))
    print('----------------------------------------------------------------------------')
    for k, v in environ.items():
        print('{}: {}'.format(k, v))

    # 让客户链接之后进入到指定的房间
    sio.enter_room(sid, 'test_room1')


@sio.on('disconnect')
def test_disconnect(sid):
    print('链接已经断开')


@sio.on('message')
def test_message(sid, data):
    print('收到客户端发来的消息: {}'.format(data))
    sio.emit('message', '这是服务器发送的广播') # 注意 这个默认是群发,只要连接到我们服务器上且监听了message时间的客户端都会收到
    sio.emit('message', '这是服务器对指定用户发送的 消息, 使用了 room=sid', room=sid) # 支队该sid会话用户发送消息
    sio.emit('message', '这是服务器对指定房间内发送的消息 room=room_id', room='test_room1') # 所有链接到这个房间的会话都会收到


@sio.on('test_leave')
def test_leave(sid,data):
    sio.leave_room(sid, room='test_room1') # 谁对这个事件发送消息,谁就会退出 'test_room1' 房间
    sio.emit('message', '{}已经离开房间'.format(sid), room='test_room1') # 在这个房间内向其他会话推送消息, 注意! 已经退出的不会再收到了


ip_port = ('', 8888) # 留空默认监听0.0.0.0


## 启动服务器
socket = eventlet.listen(ip_port)
eventlet.wsgi.server(socket, app)

Google插件使用教程

05910-k1ki49m38oh.png