websocket接口测试

一、websocket协议

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。HTML5 WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具备像 C/S 架构下桌面系统的实时通讯能力。

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

我们知道http是短连接的,反复建立和销毁连接比较耗费资源,另外http协议经常头部内容比主体内容还长也比较浪费资源;websocket可以认为就是一个内容使用载荷固定格式的socket长连接。

1.1 websocket协议报文

websocket接口测试_第1张图片
请求格式和 HTTP 请求很相似,但是还是稍有不同。
请求信息:
1、“Upgrade:WebSocket”:表示这是一个特殊的 HTTP 请求,请求的目的就是要将客户端和服务器端的通讯协议从 HTTP 协议升级到 WebSocket 协议。
2、“Sec-WebSocket-Key”:客户端浏览器需要向服务器端提供的握手信息。
应答消息:
1、“Upgrade:WebSocket”:同请求消息。
2、“Sec-WebSocket-Accept”:服务器端解析这些头信息,并在握手的过程中依据这些信息生成一个 16 位的安全密钥并返回给客户端,以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接。一旦连接建立,客户端和服务器端就可以通过这个通道双向传输数据了。

1.2 webscoket的属性、方法和事件

websocket接口测试_第2张图片

二、客户端脚本编写

2.1 Python3.5版客户端代码

首先安装websocket-client-py3模块:

pip install websocket-client-py3

2.2.1 长连接调用方式

长连接关键方法:
ws.run_forever()
python的仿js websocket写法方式,自动重连发送指令,连接时间明显减少,基本做到无遗漏数据,与HTML js的ws连接实现一样。

import websocket
from websocket import ABNF
import json
import _thread
import time

def on_message(ws, message):
    print(message)


def on_error(ws, error):
    print(error)


def on_close(ws):
    print("close connection")


def on_open(ws):
    def run(*args):
        pass
    #     content = {
    #         "mid": "1508232047195",
    #         "version": "1.0",
    #         "request": {
    #             "timestamp": 1508232047195,
    #             "sessionId": "aaaadsfasdfkop"
    #         },
    #         "params": {
    #             "audio": {
    #                 "audioType": "wav",
    #                 "sampleRate": 16000,
    #                 "channel": 1,
    #                 "sampleBytes": 2
    #             }
    #         }
    #     }
    #     ws.send(json.dumps(content))
    #     step = 3200
    #     with open(wav_path, 'rb') as f:
    #         while True:
    #             read_data = f.read(step)
    #             if read_data:
    #                 ws.send(read_data, ABNF.OPCODE_BINARY)
    #             if len(read_data) < step:
    #                 break
    #             time.sleep(0.1)
    #
    #     ws.send('', ABNF.OPCODE_BINARY)
    #     time.sleep(1.5)
    #     ws.close()
    # _thread.start_new_thread(run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp(url='ws://10.201.7.239:8063/sml/ws/log/646',
                              on_message=on_message,
                              on_error=on_error,
                              on_close=on_close)
    ws.on_open = on_open
    ws.run_forever()

2.2.2 短连接调用方式

关键方法:
ws.recv()
ws.recv_data()
查看打印结果,丢失了很多日志数据,因此建议使用长连接的调用方式。

import websocket

while True:
    ws = websocket.WebSocket()
    #建立websocket连接,这里传入了 header ,需要注意header的写入方式
    ws.connect("ws://10.201.7.239:8063/sml/ws/log/646",
               # header=["Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits",
               #         # "Sec-WebSocket-Key: 8OnwGkJ1ac82cI3g/q/WNA==",
               #         "Sec-WebSocket-Version: 13",
               #         "Upgrade: websocket"]
               )
    if ws.connected:
        print("websocket connected", "."*30)
        #接收实时数据,并打印出来
        while ws.recv():
            opcode, data = ws.recv_data()
            print(data.decode('utf-8'))
    # #关闭连接
    ws.close()
    break

2.2 html客户端代码

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>websocket通信客户端</title>
       <style>
           #baseText {
            background: black;
            color: green;
           }
       </style>
       <script type="text/javascript">
         function WebSocketTest()
         {
            var received_msg = '';
            if ("WebSocket" in window)
            {
               // 打开一个 web socket
               var ws = new WebSocket("ws://10.201.7.239:8063/sml/ws/log/646");

               // 连接建立后的回调函数
               ws.onopen = function()
               {
               // Web Socket 已连接上,使用 send() 方法发送数据
               };

               // 接收到服务器消息后的回调函数
               ws.onmessage = function (evt)
               {
                  received_msg = received_msg +  evt.data;
                  $('#baseText').html(received_msg);
               };

               // 连接关闭后的回调函数
               ws.onclose = function()
               {
                  // 关闭 websocket
                  ws.close();
                  alert("连接已关闭...");
               };
            }
            else
            {
               // 浏览器不支持 WebSocket
               alert("您的浏览器不支持 WebSocket!");
            }
         }

      </script>
       <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
   </head>

   <body>
        <textarea id="baseText" style="width: 800px; height: 800px; margin: 0px;"></textarea><br>
        <input type="button" onclick="WebSocketTest()" value="获取组件日志打印">
   </body>
</html>

三、通信数据包截获及通信过程分析

使用过滤器表达式“websocket”过滤wireshark拦截数据包:
websocket接口测试_第3张图片
追踪数据流可以清晰看清websocket通信过程,首先使用http建立连接,然后升级到了websocket协议。
websocket接口测试_第4张图片
再看具体数据流也确实如此,先用两个http包建立连接,而后是websocket通信(问题是不清楚websocket内容是怎么编码的,有些就显示不了原始内容)
websocket接口测试_第5张图片
参考:
https://www.cnblogs.com/lsdb/p/10949766.html
https://blog.csdn.net/julia922/article/details/89334200

你可能感兴趣的:(python)