• python+socket+jq实现web页面实时输出结果


    例如有这样一个需求:

    在终端上进行ping操作,现在想把这个这个操作放到web页面上进行,并且实现实时输出的效果。

    来分析下具体实现过程

    第一步,传统的http请求实现这个有点不太友好,因为这里边是一个请求,请求中间隔输出结果。  可以使用长轮询,这个以后再研究。

    这种情况用websocket比较好。

    然后再来解决几个疑惑,

    怎么去写服务端的websocket?

    方法: 这个选择比较多,python的很多框架里边都带有websocket模块,例如gevent-websocket,dwebsocket,flask_sockets

    但是使用api却有不同,其实这些都是对socket进行来新的封装,所以这里用最原始的socket进行编程。

    怎么发送websocket请求?

    方法:发送websocket请求这个方法也比较多,有专门的第三方模块,例如websocket_client,jquery。这次是打算在web页面上显示,所以用jquery自带的api来请求服务端。

    WebSocket 和 Socket 的区别,websocket 能连 socket 吗

    方法:就像Java和JavaScript,并没有什么太大的关系,但又不能说完全没关系。可以这么说,socket并不是一个协议,而是抽象出来的一层,应用于应用层和传输控制层之间的一组接口,socket是传输控制层协议,websocket是应用层协议。 jquery自带的api能有直接请求socket。

    下边就直接上代码了

    服务端:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import socket
    import base64
    import hashlib
    
    
    def get_headers(data):
        """
        将请求头格式化成字典
        :param data:
        :return:
        """
        header_dict = {}
        data = str(data, encoding='utf-8')
    
        header, body = data.split('
    
    ', 1)
        header_list = header.split('
    ')
        for i in range(0, len(header_list)):
            if i == 0:
                if len(header_list[i].split(' ')) == 3:
                    header_dict['method'], header_dict['url'], header_dict['protocol'] = header_list[i].split(' ')
            else:
                k, v = header_list[i].split(':', 1)
                header_dict[k] = v.strip()
        return header_dict
    
    
    def send_msg(conn, msg_bytes):
        """
        WebSocket服务端向客户端发送消息
        :param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
        :param msg_bytes: 向客户端发送的字节
        :return:
        """
        import struct
    
        token = b"x81"
        length = len(msg_bytes)
        if length < 126:
            token += struct.pack("B", length)
        elif length <= 0xFFFF:
            token += struct.pack("!BH", 126, length)
        else:
            token += struct.pack("!BQ", 127, length)
    
        msg = token + msg_bytes
        conn.send(msg)
        return True
    
    
    def run():
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind(('0.0.0.0', 8003))
        sock.listen(5)
    
        conn, address = sock.accept()
        print(address)
        data = conn.recv(1024)
        print(data)
        headers = get_headers(data)
        response_tpl = "HTTP/1.1 101 Switching Protocols
    " 
                       "Upgrade:websocket
    " 
                       "Connection:Upgrade
    " 
                       "Sec-WebSocket-Accept:%s
    " 
                       "WebSocket-Location:ws://%s%s
    
    "
    
        value = headers['Sec-WebSocket-Key'] + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
        ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
        response_str = response_tpl % (ac.decode('utf-8'), headers['Host'], headers['url'])
        conn.send(bytes(response_str, encoding='utf-8'))
    
        while True:
            try:
                info = conn.recv(8096)
            except Exception as e:
                info = None
            if not info:
                break
            payload_len = info[1] & 127
            if payload_len == 126:
                extend_payload_len = info[2:4]
                mask = info[4:8]
                decoded = info[8:]
            elif payload_len == 127:
                extend_payload_len = info[2:10]
                mask = info[10:14]
                decoded = info[14:]
            else:
                extend_payload_len = None
                mask = info[2:6]
                decoded = info[6:]
    
            bytes_list = bytearray()
            for i in range(len(decoded)):
                chunk = decoded[i] ^ mask[i % 4]
                bytes_list.append(chunk)
            body = str(bytes_list, encoding='utf-8')
    
            import subprocess
            p = subprocess.Popen('ping -c5 www.baidu.com', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            lines = []
            for line in iter(p.stdout.readline, b''):
                line = line.rstrip().decode('utf8')
                send_msg(conn, line.encode('utf-8'))
    
        sock.close()
    
    
    if __name__ == '__main__':
        run()
    View Code

    客户端:

    <!DOCTYPE html >
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title></title>
        <script src="jquery-2.1.4.min.js"></script>
        <script type="text/javascript">
        $(function () {
            var socket = new WebSocket("ws://127.0.0.1:8003");
            $('#backup_all').click(function () {
                console.log(window.location.host)
                console.log(socket);
                // socket.onopen = function () {
                //     console.log('WebSocket open');//成功连接上Websocket
                //     socket.send('ls');//发送数据到服务端
                // };
                socket.send('ls');
                    console.log('WebSocket open');//成功连接上Websocket
    
                socket.onmessage = function (e) {
                    console.log('message: ' + e.data);//打印服务端返回的数据
                    //$('#messagecontainer').prepend('<p><pre>' + e.data + '</pre></p>');
                    //$('#messagecontainer').prepend('<hr />');
                    $('#messagecontainer').append(e.data+'<br/>');
    
                };
            });
        });
        </script>
    </head>
    <body>
    
    <button style="margin: 20px;height: 40px;background-color: #00ff00;" type="button" id="backup_all" value="backup_all">
        执行Shell脚本
    </button>
    <h3 style="margin: 20px;">脚本执行结果:</h3>
    <div id="messagecontainer" style="margin: 20px;">
    </div>
    <hr/>
    </body>
    </html>
    View Code

    结果:

    https://www.cnblogs.com/ssyfj/p/9245150.html

    https://yq.aliyun.com/articles/656918

    https://www.cnblogs.com/mengqingjian/p/8530994.html

  • 相关阅读:
    28、vSocket模型详解及select应用详解
    27、通过visual s'tudio 验证 SOCKET编程:搭建一个TCP服务器
    26、TCP服务器原理
    8、字符串操作
    9、内存操作
    ESP32作为接入点AP
    ·通过wifi_scan学习esp32wifi程序编写
    10、指针变量基础
    关于wifi网络基本原理了解
    开发团队中命名规范的重要性
  • 原文地址:https://www.cnblogs.com/sdadx/p/11325672.html
Copyright © 2020-2023  润新知