
最近做项目写了一个小 websocket 服务器但是有报错我自己没法搞定求大神解救
import socket import time import hashlib import base64 import struct import threading import chardet cOnnlist= [] s = socket.socket() host = "0.0.0.0" port = 1999 s.bind((host, port)) s.listen(500) def getheads(data): data = data.decode() datasplit = data.split("\r\n") datasplit = datasplit[1:-2] headslist = {} for i in datasplit: k,v = i.split(":",1) headslist[k] = v.replace(' ','') return headslist def _get_data(info, setcode): payload_len = info[1] & 127 fin = 1 if info[0] & 128 == 128 else 0 opcode = info[0] & 15 if payload_len == 126: mask = info[4:8] decoded = info[8:] elif payload_len == 127: mask = info[10:14] decoded = info[14:] else: 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) if opcode == 0x00: opcode = setcode if opcode == 0x01: body = str(bytes_list, encoding='utf-8',errors='ignore') return fin, opcode, body else: body = decoded return fin, opcode, body def recv(conn): msg = '' opcode = 0x00 while True: raw_data = b'' while True: section = conn.recv(1024) raw_data += section if len(section) < 1024: break fin, _opcode, fragment = _get_data(raw_data,opcode) opcode = _opcode if _opcode != 0x00 else opcode msg += fragment if fin == 1: break return msg def send(conn,msg,fin=True): data = struct.pack('B', 129) if fin else struct.pack('B', 0) msg_len = len(msg) if msg_len <= 125: data += struct.pack('B', msg_len) elif msg_len <= (2**16 - 1): data += struct.pack('!BH', 126, msg_len) elif msg_len <= (2**64 - 1): data += struct.pack('!BQ', 127, msg_len) else: while True: fragment = msg[:(2**64 - 1)] msg -= fragment if msg > (2**64 - 1): conn.send(fragment, False) else: conn.send(fragment) data += bytes(msg,encoding='utf-8',errors='ignore') conn.send(data) def shakehands(conn): data = conn.recv(1024) heads = getheads(data) msg = heads["Sec-WebSocket-Key"] key = msg + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' ser_key = hashlib.sha1(key.encode('utf-8')).digest() token = base64.b64encode(ser_key) message = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "+bytes.decode(token)+"\r\nWebSocket-Origin: "+str(heads["Origin"])+"\r\nWebSocket-Location: ws://"+str(heads["Host"])+"\r\n\r\n" conn.send(message.encode()) connlist.append(conn) def websockethandle(conn,addr): shakehands(conn) ip,port = addr print(ip+" 连入") print("当前用户数:"+str(len(connlist))) while True: try: data= recv(conn) except Exception as e: print(e) print(ip+" 断开") conn.close() connlist.remove(conn) print("当前用户数:"+str(len(connlist))) break for i in connlist: if i != conn: send(i,data) while True: conn,addr = s.accept() threading.Thread(target=websockethandle,args=(conn,addr,)).start() 1 anjianshi 2020-11-06 20:28:11 +08:00 排查一下所有 + 号的地方?是不是在把字符串和 bytes 进行拼接。 并且看错误信息,是左侧字符串,右侧 bytes 。例如 a = 'abc' b = b'def' a + b 会报这个 |
2 anjianshi 2020-11-06 20:35:45 +08:00 粗看了一下,你看是不是这样的问题: 1. def recv(conn) 里调用 _get_data(raw_data) 时传入的 raw_data 是 bytes 2. def _get_data(info, setcode) 里收到的 info 是 bytes,函数里的 decoded 变量是基于 info 的,所以也是 bytes, 然后函数返回值 body 在最下面的一个 if 分支,就等于 decoded 变量,所以返回的也是 bytes 3. def recv(conn) 获取到 _get_data() 的返回值并写入 fragment 变量,但按上面的流程,fragment 是一个 bytes 4. def recv(conn) 执行了 msg += fragment,msg 是 str,fragment 是 bytes,最终报错 |
3 dd99iii 2020-11-06 20:36:37 +08:00 message = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "+bytes.decode(token)+"\r\nWebSocket-Origin: "+str(heads["Origin"])+"\r\nWebSocket-Location: ws://"+str(heads["Host"])+"\r\n\r\n" 我猜这个是 bytes: bytes.decode(token) |
5 CEBBCAT 2020-11-06 21:37:28 +08:00 via Android 明白了吗?#为什么而活? |
6 ysc3839 2020-11-07 01:07:08 +08:00 “客户端断开连接”是在哪出现的?你的代码里没有呀? |
7 qile1 2020-11-07 10:45:43 +08:00 via Android msg=b''试试 |
8 dahuahua 2020-11-07 16:48:18 +08:00 为什么不打印日志 |