Websocket

Posted 陌维

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Websocket相关的知识,希望对你有一定的参考价值。

flask中的socket

需要将run,wsgi替换成websocket

群聊

# 不需要记住 但是要知道是什么模块驱使Flask 支持Websocket
# gevent-websocket
# 以下代码 和 gevent-websocket 使用方式 请记录在案
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket.server import WSGIServer
from geventwebsocket.websocket import WebSocket  # 语法提示

from flask import Flask, request, render_template
app = Flask(__name__)

socket_list = []

@app.route("/ws")
def ws():
    sock = request.environ.get("wsgi.websocket")  # type:WebSocket
    socket_list.append(sock)
    print(socket_list)
    # 1 : 连接打开
    # 2 : 客户端主动关闭连接
    # 3 : 连接关闭 由服务器发起
    # 0 : 连接中。。。。。。
    while 1:
        try:
            msg = sock.receive()  # hello
        except:
            socket_list.remove(sock)
            break
        for so in socket_list:
            if so == sock:
                continue
            try:
                so.send(msg)
            except:
                continue

    return "200OK"

    # return "200 OK"


@app.route("/")
def index():
    return render_template("ws_client.html")


if __name__ == __main__:
    # app.run()
    http_serv = WSGIServer(("0.0.0.0", 9527), app, handler_class=WebSocketHandler)  # environment
    http_serv.serve_forever()

 

技术图片
"""
{‘GATEWAY_INTERFACE‘: ‘CGI/1.1‘, ‘SERVER_SOFTWARE‘: ‘gevent/1.4 Python/3.6‘, ‘SCRIPT_NAME‘: ‘‘, ‘wsgi.version‘: (1, 0), ‘wsgi.multithread‘: False, ‘wsgi.multiprocess‘: False, ‘wsgi.run_once‘: False, ‘wsgi.url_scheme‘: ‘http‘, ‘wsgi.errors‘: <_io.TextIOWrapper name=‘<stderr>‘ mode=‘w‘ encoding=‘UTF-8‘>, ‘SERVER_NAME‘: ‘DESKTOP-U8U37NO‘, ‘SERVER_PORT‘: ‘9527‘, ‘REQUEST_METHOD‘: ‘GET‘, ‘PATH_INFO‘: ‘/ws‘, ‘QUERY_STRING‘: ‘‘, ‘SERVER_PROTOCOL‘: ‘HTTP/1.1‘, ‘REMOTE_ADDR‘: ‘127.0.0.1‘, ‘REMOTE_PORT‘: ‘56107‘, ‘HTTP_HOST‘: ‘127.0.0.1:9527‘, ‘HTTP_USER_AGENT‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0‘, ‘HTTP_ACCEPT‘: ‘text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8‘, ‘HTTP_ACCEPT_LANGUAGE‘: ‘zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2‘, ‘HTTP_ACCEPT_ENCODING‘: ‘gzip, deflate‘, ‘HTTP_CONNECTION‘: ‘keep-alive‘, ‘HTTP_UPGRADE_INSECURE_REQUESTS‘: ‘1‘, ‘wsgi.input‘: <gevent.pywsgi.Input object at 0x0000021596BF3B28>, ‘wsgi.input_terminated‘: True, ‘werkzeug.request‘: <Request ‘http://127.0.0.1:9527/ws‘ [GET]>}
"""

"""
{‘GATEWAY_INTERFACE‘: ‘CGI/1.1‘, ‘SERVER_SOFTWARE‘: ‘gevent/1.4 Python/3.6‘, ‘SCRIPT_NAME‘: ‘‘, ‘wsgi.version‘: (1, 0), ‘wsgi.multithread‘: False, ‘wsgi.multiprocess‘: False, ‘wsgi.run_once‘: False, ‘wsgi.url_scheme‘: ‘http‘, ‘wsgi.errors‘: <_io.TextIOWrapper name=‘<stderr>‘ mode=‘w‘ encoding=‘UTF-8‘>, ‘SERVER_NAME‘: ‘DESKTOP-U8U37NO‘, ‘SERVER_PORT‘: ‘9527‘, ‘REQUEST_METHOD‘: ‘GET‘, ‘PATH_INFO‘: ‘/ws‘, ‘QUERY_STRING‘: ‘‘, ‘SERVER_PROTOCOL‘: ‘HTTP/1.1‘, ‘REMOTE_ADDR‘: ‘127.0.0.1‘, ‘REMOTE_PORT‘: ‘56249‘, ‘HTTP_HOST‘: ‘127.0.0.1:9527‘, ‘HTTP_CONNECTION‘: ‘Upgrade‘, ‘HTTP_PRAGMA‘: ‘no-cache‘, ‘HTTP_CACHE_CONTROL‘: ‘no-cache‘, ‘HTTP_USER_AGENT‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36‘, ‘HTTP_UPGRADE‘: ‘websocket‘, ‘HTTP_ORIGIN‘: ‘http://localhost:63342‘, ‘HTTP_SEC_WEBSOCKET_VERSION‘: ‘13‘, ‘HTTP_ACCEPT_ENCODING‘: ‘gzip, deflate, br‘, ‘HTTP_ACCEPT_LANGUAGE‘: ‘zh-CN,zh;q=0.9‘, ‘HTTP_COOKIE‘: ‘session=a11311f1-7927-4879-a8f5-04dbb6535410‘, ‘HTTP_SEC_WEBSOCKET_KEY‘: ‘71CDvLfOHw8dkO9SiEGMjg==‘, ‘HTTP_SEC_WEBSOCKET_EXTENSIONS‘: ‘permessage-deflate; client_max_window_bits‘, ‘wsgi.input‘: <gevent.pywsgi.Input object at 0x000002DFB6C93CA8>, ‘wsgi.input_terminated‘: True, ‘wsgi.websocket_version‘: ‘13‘, ‘wsgi.websocket‘: <geventwebsocket.websocket.WebSocket object at 0x000002DFB6CC4660>, ‘werkzeug.request‘: <Request ‘http://127.0.0.1:9527/ws‘ [GET]>}
"""
注释

 

技术图片
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
  <title>Bootstrap 101 Template</title>
  <!-- Bootstrap -->
</head>
<body>
<h1>你好,世界!</h1>
<input type="text" id="text"> <button id="send">点击发送消息</button>
<div id="content_list">

</div>
</body>
<script type="application/javascript">
  var ws = new WebSocket("ws://192.168.14.26:9527/ws");
  // 回调函数
  // onopen websocket连接建立完成 status == 1
  // ws.onopen = function () {
  //     ws.send("Hello");
  // };
  // onmessage websocket 接收到消息时 执行
  ws.onmessage = function (eventMessage) {
      var s = eventMessage.data;
      var p = document.createElement("p");
      p.innerText = s;
      document.getElementById("content_list").appendChild(p);
  };

  // ws.onclose

  // ws.send("123");

  document.getElementById("send").addEventListener("onclick",function () {
      var st = document.getElementById("text").value();
      ws.send(st);
  })
</script>
</html>
ws_client

 

点对点

import json

from geventwebsocket.handler import WebSocketHandler # ws 协议请求处理
from geventwebsocket.server import WSGIServer # 替换Flask 原有的WSGI
from geventwebsocket.websocket import WebSocket # 语法提示

from flask import Flask, request, render_template

app = Flask(__name__)

socket_dict = {}

@app.route("/ws/<username>")
def ws(username):
    sock = request.environ.get("wsgi.websocket",None) # type:WebSocket
    # 1.不是WS协议上来的请求 None
    # 2.WS协议认证失败 None
    if not sock :
        return "请使用WS协议连接"

    # if socket_dict.get(username).closed:
    #     return "已经登陆"

    socket_dict[username] = sock
    print(len(socket_dict),socket_dict)

    while True:
        msg = sock.receive()
        print(type(msg),msg)
        msg_dict = json.loads(msg)
        recv = msg_dict.get("recv")
        recv_sock = socket_dict.get(recv)
        recv_sock.send(msg)


@app.route("/")
def index():
    return render_template("ws_client_2.html")

if __name__ == __main__:
    http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler)
    http_serv.serve_forever()

 

技术图片
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
  <title>Bootstrap 101 Template</title>
  <!-- Bootstrap -->
</head>
<body>
<h1>你好,世界!</h1>
你的名字:<input type="text" id="username"><button id="createws">登录聊天室</button>
<p><input type="text" id="recv">发送<input type="text" id="text">内容 <button id="send">点击发送消息</button></p>
<div id="content_list">

</div>
</body>
<script type="application/javascript">
  var ws = null;
  document.getElementById("createws").onclick = function () {
      var username = document.getElementById("username").value;
      ws = new WebSocket("ws://192.168.14.26:9527/ws/"+username);
      ws.onopen = function () {
          alert("欢迎进入九聊");
      };
      ws.onmessage = function (eventMessage) {
          var msg = JSON.parse(eventMessage.data);
          console.log(msg);
          var p = document.createElement("p");
          p.innerText = msg.sender + " : " + msg.msg;
          document.getElementById("content_list").appendChild(p);
      };
  };



  // 回调函数
  // onopen websocket连接建立完成 status == 1
  // ws.onopen = function () {
  //     ws.send("Hello");
  // };
  // onmessage websocket 接收到消息时 执行


  // ws.onclose

  // ws.send("123");

  document.getElementById("send").onclick = function () {
      var recv = document.getElementById("recv").value;
      var msg = document.getElementById("text").value;
      var sender = document.getElementById("username").value;

      var send_msg = {
          "sender":sender,
          "recv": recv,
          "msg":msg
      };
      console.log(send_msg);

      ws.send(JSON.stringify(send_msg));
  };
</script>
</html>
ws_client_2

 

以上是关于Websocket的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS中的Websockets。从服务器端WebSocket客户端调用WebSocketServer

websocket弹簧启动设置

WebSocket - 关闭握手 Gorilla

WebSocket 在 1000 条消息后关闭

使用 FFmpeg 通过管道输出视频片段

低延迟 websocket html 5 游戏的数据包大小