websocket

2021-04-13 10:27

阅读:432

YPE html>

标签:ike   its   rtb   管道   浏览器   input框   city   key   contain   


阅读目录

一、websockt

二、实战应用

1 websocket

1.1 简述

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

1.2 原理

技术图片

1.2.1 一个小例子熟悉websocket原理

a.启动服务端,等待客户端连接
b.小强来连接,服务端允许
c.小强立即发送一个“握手信息”

    GET /xxxx HTTP/1.1\r\n
    Host: 127.0.0.1:8002\r\n
    Connection: Upgrade\r\n
    Pragma: no-cache\r\n
    Cache-Control: no-cache\r\n
    Upgrade: websocket\r\n
    Origin: http://localhost:63342\r\nSec-WebSocket-Version: 13\r\n
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36\r\n
    Accept-Encoding: gzip, deflate, br\r\n
    Accept-Language: zh-CN,zh;q=0.9\r\n
    Cookie: csrftoken=ojyruuaF3Tk0OToIrXy1sRSdSk3SeDgd6Ti3jocEXAuEExaMtxjhJglpenj6Iq8F\r\n
    Sec-WebSocket-Key: 4NZY2fTOr691upgWe2yq7w==\r\n ########  这里 ########
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n

d.服务端接收握手信息后需要对数据进行加密,给客户端返回

     - 4NZY2fTOr691upgWe2yq7w + magic_string(魔法字符串) 
     - sha1
     - base64 
        response_tpl = "HTTP/1.1 101 Switching Protocols\r\n"               "Upgrade:websocket\r\n"               "Connection: Upgrade\r\n"               "Sec-WebSocket-Accept: 加密之后的结果\r\n"               "WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n"
    通信建立,双方可以进行互相通信:

e.小强给服务端发送消息:

   读取第二个字节的后7位
        127:10,4,数据
        126:4,4,数据
      

f.服务端给客户端发送消息:

    token = b"\x81"
    length = len(msg_bytes)
    if length 

1.3 socket.io与websocket

  • https://www.jianshu.com/p/2ec3d20341ab

1.4 python实现示例

  • flask-socketio文档: https://flask-socketio.readthedocs.io/en/latest/

1.5 golang实现示例

1.5.1 后端

package main

import (
    "errors"
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
    "sync"
    "time"
)

var wsUpgrader = websocket.Upgrader{
    //允许所有的cors跨域请求
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

type wsMessage struct {
    messageType int
    data []byte
}

type wsConnection struct {
    wsSocket *websocket.Conn //底层websocket
    inChan chan *wsMessage   //读队列
    outChan chan *wsMessage  //写队列

    mutex sync.Mutex   //避免重复关闭管道
    isClosed bool
    closeChan chan byte  //关闭通知
}


func(wsConn *wsConnection) wsReadLoop(){
    for{
        //读取一个message
        mesType,data,err := wsConn.wsSocket.ReadMessage()
        if err != nil{
            goto error
        }
        req := &wsMessage{messageType:mesType, data:data}

        //放入请求队列
        select{
        case wsConn.inChan

1.5.2 前端



Click "Open" to create a connection to the server, "Send" to send a message to the server and "Close" to close the connection. You can change the message and send multiple times.

2 实战应用

2.1 协作编辑

2.1.1 简介

多人实时操作一个资源,如钉钉协作excel文档,更多可以了解下面两部分内容

  • https://www.cnblogs.com/powertoolsteam/p/onlineexcel.html
  • https://www.jianshu.com/p/a3b350063cb5

2.1.2 需求实现

  • web端多人在线协作编辑表格,python+flask+vue+socket.io实现

2.1.3 前端

协作编辑

名称
年龄
性别
爱好
技能

2.1.4 后端

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
CORS(app, supports_credentials=True, resources=r'/*')                              # http跨域问题
socketio = SocketIO(app, async_mode=async_mode, cors_allowed_origins='*')          # cors_allowed_origins解决跨域

@app.route('/input-change', methods=['POST'])   # http协议接受input change信息
def input_change():
    """
    broadcast=True,发送广播,所有连接到socket.io的链接都会接受到信息
    """
    emit('input-change', request.json, broadcast=True, namespace='/test')    
    return "success!"

@socketio.on('connect', namespace='/test')
def mtest_connect():
    global thread
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(background_thread)
    print("靓仔你来了呀...")
    emit('my_response', {'data': 'Connected', 'count': 0})

@socketio.on('disconnect', namespace='/test')
def mtest_disconnect():
    print('Client disconnected', request.sid)


if __name__ == '__main__':
    socketio.run(app, debug=True)

2.1.5 总结

  • 简单了实现了需求,但是协作编辑远远比这个要复杂的多,代码后端的处理直接选用了广播模式,真实场景肯定会有所偏差。这里推荐一个优秀的前端excel编辑器-葡萄城spreadjs

2.2 实时聊天室

github - 协作编辑及实时聊天室

websocket

标签:ike   its   rtb   管道   浏览器   input框   city   key   contain   

原文地址:https://www.cnblogs.com/zhangliang91/p/12266135.html


评论


亲,登录后才可以留言!