Socket转换WebSocket简单案例

创建WebSocket(服务端)

# -*- coding: utf-8 -*-
import socket
from hashlib import sha256, sha1
import base64
import struct
import sys


sock = socket.socket()
# sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 8080))
sock.listen()

conn, addr = sock.accept()
print('连接来自: %s, 地址: %s' % (conn, addr))

# 等待客户端发送websocket数据
data = conn.recv(4096)


# 客户端请求头格式
"""
    b'
        GET / HTTP/1.1\r\n
        Host: 127.0.0.1:\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\n
        Sec-WebSocket-Version: \r\n
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36\r\n
        Accept-Encoding: gzip, deflate, br\r\n
        Accept-Language: zh-CN,zh;q=0.8\r\n
        Sec-WebSocket-Key: +uL/aiakjNABjEoMzAqm6Q==\r\n
        Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n
    '
"""


def get_headers(*args, **kwargs):
    """
        解析请求头,请求体数据
    :param data:
    :return:
    """
    header_dict = {}
    data = kwargs.get("data", "")
    if data and isinstance(data, bytes):
        str_data = data.decode("utf-8")
        if str_data:
            headers, body = str_data.split("\r\n\r\n")
            headers_list = headers.split("\r\n")
            for i in range(len(headers_list)):
                if i == 0:
                    flag = headers_list[i].split(" ")
                    if flag:
                        header_dict["method"], header_dict["url"], header_dict["protocol"] = \
                            headers_list[i].split(" ")
                else:
                    k, v = headers_list[i].split(": ")
                    header_dict[k] = v.strip()
    return header_dict


# 处理请求头信息为字典
headers = get_headers(data=data)

# 响应头
# 对请求头中的sec-websocket-key进行加密后传输
response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
               "Upgrade: websocket\r\n" \
               "Connection: Upgrade\r\n" \
               "Sec-WebSocket-Accept: %s\r\n" \
               "WebSocket-Location: ws://%s%s\r\n\r\n"
# 默认混淆串
magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'

# 拼接响应头内容
sec_key = headers.get("Sec-WebSocket-Key", "")
host = headers.get("Host", "")
url = headers.get("url", "")
sec_key_sign = sec_key + magic_string
ac = base64.b64encode(sha1(sec_key_sign.encode("utf-8")).digest())
response_tpl = response_tpl % (ac.decode("utf-8"), host, url)

# 返回响应头给客户端信息
conn.send(response_tpl.encode("utf-8"))


# 解析客户端发送的数据
def get_data(*args, **kwargs):
    """
        解析客户端发送的数据
    :param args:
    :param kwargs:
    :return:
    """
    body = ""
    data = kwargs.get('data', "")
    if data:
        payload_len = data[1] & 127
        if payload_len == 126:
            extend_payload_len = data[2:4]
            mask = data[4:8]
            decoded = data[8:]
        elif payload_len == 127:
            extend_payload_len = data[2:10]
            mask = data[10:14]
            decoded = data[14:]
        else:
            extend_payload_len = None
            mask = data[2:6]
            decoded = data[6:]
        bytes_list = bytearray()
        for i in range(len(decoded)):
            chunk = decoded[i] ^ mask[i % 4]
            bytes_list.append(chunk)
        try:
            body = str(bytes_list, encoding="utf-8")
        except Exception as e:
            sys.exit()
    return body


def send_data(*args, **kwargs):
    """
        服务端发送数据给客户端
    :param args:
    :param kwargs:
    :return:
    """
    sdata = ""
    data = kwargs.get("data", "")
    if data:
        token = b"\x81"
        length = len(data)
        if length < 126:
            token += struct.pack("B", length)
        elif length <= 0xFFFF:
            token += struct.pack("!BH", 126, length)
        else:
            token += struct.pack("!BQ", 127, length)
        sdata = token + data
    return sdata


# 循环接收客户端数据并将接收数据++ok响应给客户端
while True:
    try:
        try:
            data = conn.recv(4096)
        except KeyboardInterrupt as e:
            conn.close()
            sys.exit()
        else:
            print('接收数据bytes==', data)
            body = get_data(data=data)
            print('接收数据str==: %s' % body)
            body = body + "++ok"
            sdata = send_data(data=body.encode("utf-8"))
            print('发送数据bytes==: %s' % sdata)
            conn.send(sdata)
    except Exception as e:
        conn.close()
        sys.exit()

连接WebSocket(客户端)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Websocket</title>
</head>
<body>

</body>
</html>
<script>
    ws = new WebSocket("ws://127.0.0.1:8080");
    ws.onopen = function (ev) {
        console.log("连接成功!")
    }
    ws.onmessage = function (ev) {
        console.log(ev)
    }
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值