最近做项目写了一个小 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
为什么不打印日志
|