Python上的多线程websocket服务器
请帮助我改进此代码:Python上的多线程websocket服务器,python,multithreading,websocket,Python,Multithreading,Websocket,请帮助我改进此代码: import base64 import hashlib import threading import socket class WebSocketServer: def __init__(self, host, port, limit, **kwargs): """ Initialize websocket server. :param host: Host name as IP address or tex
import base64
import hashlib
import threading
import socket
class WebSocketServer:
def __init__(self, host, port, limit, **kwargs):
"""
Initialize websocket server.
:param host: Host name as IP address or text definition.
:param port: Port number, which server will listen.
:param limit: Limit of connections in queue.
:param kwargs: A dict of key/value pairs. It MAY contains:<br>
<b>onconnect</b> - function, called after client connected.
<b>handshake</b> - string, containing the handshake pattern.
<b>magic</b> - string, containing "magic" key, required for "handshake".
:type host: str
:type port: int
:type limit: int
:type kwargs: dict
"""
self.host = host
self.port = port
self.limit = limit
self.running = False
self.clients = []
self.args = kwargs
def start(self):
"""
Start websocket server.
"""
self.root = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.root.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.root.bind((self.host, self.port))
self.root.listen(self.limit)
self.running = True
while self.running:
client, address = self.root.accept()
if not self.running: break
self.handshake(client)
self.clients.append((client, address))
onconnect = self.args.get("onconnect")
if callable(onconnect): onconnect(self, client, address)
threading.Thread(target=self.loop, args=(client, address)).start()
self.root.close()
def stop(self):
"""
Stop websocket server.
"""
self.running = False
def handshake(self, client):
handshake = 'HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Accept: %s\r\n\r\n'
handshake = self.args.get('handshake', handshake)
magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
magic = self.args.get('magic', magic)
header = str(client.recv(1000))
try:
res = header.index("Sec-WebSocket-Key")
except ValueError:
return False
key = header[res + 19: res + 19 + 24]
key += magic
key = hashlib.sha1(key.encode())
key = base64.b64encode(key.digest())
client.send(bytes((handshake % str(key,'utf-8')), 'utf-8'))
return True
def loop(self, client, address):
"""
:type client: socket
"""
while True:
message = ''
m = client.recv(1)
while m != '':
message += m
m = client.recv(1)
fin, text = self.decodeFrame(message)
if not fin:
onmessage = self.args.get('onmessage')
if callable(onmessage): onmessage(self, client, text)
else:
self.clients.remove((client, address))
ondisconnect = self.args.get('ondisconnect')
if callable(ondisconnect): ondisconnect(self, client, address)
client.close()
break
def decodeFrame(self, data):
if (len(data) == 0) or (data is None):
return True, None
fin = not(data[0] & 1)
if fin:
return fin, None
masked = not(data[1] & 1)
plen = data[1] - (128 if masked else 0)
mask_start = 2
if plen == 126:
mask_start = 4
plen = int.from_bytes(data[2:4], byteorder='sys.byteorder')
elif plen == 127:
mask_start = 10
plen = int.from_bytes(data[2:10], byteorder='sys.byteorder')
mask = data[mask_start:mask_start+4]
data = data[mask_start+4:mask_start+4+plen]
decoded = []
i = 0
while i < len(data):
decoded.append(data[i] ^ mask[i%4])
i+=1
text = str(bytearray(decoded), "utf-8")
return fin, text
def sendto(self, client, data, **kwargs):
"""
Send <b>data</b> to <b>client</b>. <b>data</b> can be of type <i>str</i>, <i>bytes</i>, <i>bytearray</i>, <i>int</i>.
:param client: Client socket for data exchange.
:param data: Data, which will be sent to the client via <i>socket</i>.
:type client: socket
:type data: str|bytes|bytearray|int|float
"""
if type(data) == bytes or type(data) == bytearray:
frame = data
elif type(data) == str:
frame = bytes(data, kwargs.get('encoding', 'utf-8'))
elif type(data) == int or type(data) == float:
frame = bytes(str(data), kwargs.get('encoding', 'utf-8'))
else:
return None
framelen = len(frame)
head = bytes([0x81])
if framelen < 126:
head += bytes(int.to_bytes(framelen, 1, 'big'))
elif 126 <= framelen < 0x10000:
head += bytes(126)
head += bytes(int.to_bytes(framelen, 2, 'big'))
else:
head += bytes(127)
head += bytes(int.to_bytes(framelen, 8, 'big'))
client.send(head + frame)
导入base64
导入hashlib
导入线程
导入套接字
类WebSocketServer:
定义初始化(自身、主机、端口、限制,**kwargs):
"""
初始化websocket服务器。
:param host:主机名作为IP地址或文本定义。
:param port:端口号,哪个服务器将侦听。
:param limit:队列中连接的限制。
:param kwargs:键/值对的dict。它可能包含:
onconnect—函数,在客户端连接后调用。
握手-字符串,包含握手模式。
魔术-字符串,包含“魔术”键,“握手”所需。
:类型主机:str
:类型端口:int
:类型限制:int
:类型kwargs:dict
"""
self.host=host
self.port=端口
self.limit=限制
self.running=False
self.clients=[]
self.args=kwargs
def启动(自):
"""
启动websocket服务器。
"""
self.root=socket.socket(socket.AF\u INET,socket.SOCK\u STREAM)
self.root.setsockopt(socket.SOL\u socket,socket.SO\u REUSEADDR,1)
self.root.bind((self.host,self.port))
self.root.listen(self.limit)
self.running=True
自运行时:
客户端,地址=self.root.accept()
如果不是自动运行:中断
自我握手(客户端)
self.clients.append((客户机,地址))
onconnect=self.args.get(“onconnect”)
如果可调用(onconnect):onconnect(self、client、address)
threading.Thread(target=self.loop,args=(客户机,地址)).start()
self.root.close()
def停止(自):
"""
停止websocket服务器。
"""
self.running=False
def握手(自我、客户端):
握手='HTTP/1.1 101交换协议\r\n连接:升级\r\n升级:websocket\r\nSec websocket接受:%s\r\n\r\n'
handshake=self.args.get('handshake',handshake)
magic=“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”
magic=self.args.get('magic',magic)
header=str(client.recv(1000))
尝试:
res=标题索引(“Sec WebSocket键”)
除值错误外:
返回错误
key=标题[res+19:res+19+24]
钥匙+=魔术
key=hashlib.sha1(key.encode())
key=base64.b64编码(key.digest())
发送(字节((握手%str(键,'utf-8')),'utf-8'))
返回真值
def循环(自身、客户端、地址):
"""
:类型客户端:套接字
"""
尽管如此:
消息=“”
m=客户端.recv(1)
而m!='':
消息+=m
m=客户端.recv(1)
fin,text=self.decodeFrame(消息)
如果不是fin:
onmessage=self.args.get('onmessage')
如果可调用(onmessage):onmessage(self、client、text)
其他:
self.clients.remove((客户端,地址))
ondisconnect=self.args.get('ondisconnect')
如果可调用(ondisconnect):ondisconnect(self、client、address)
client.close()
打破
def解码帧(自身,数据):
如果(len(data)==0)或(data为无):
返回True,无
fin=not(数据[0]&1)
如果是fin:
返回鳍,无
屏蔽=未屏蔽(数据[1]&1)
plen=数据[1]-(如果屏蔽,则为128,否则为0)
掩码_开始=2
如果plen==126:
掩码_开始=4
plen=int.from_字节(数据[2:4],byteorder='sys.byteorder')
elif plen==127:
掩码_开始=10
plen=int.from_字节(数据[2:10],byteorder='sys.byteorder')
掩码=数据[掩码开始:掩码开始+4]
数据=数据[屏蔽启动+4:屏蔽启动+4+plen]
解码=[]
i=0
而i
所以你的代码不起作用。您可以使用而不是线程(不在Windows*上),或者如果您希望同时支持多个客户端,则可以使用
如果选择多处理,请尝试以下操作:
client.py:
import socket
def main():
s = socket.socket()
s.connect(("localhost", 5555))
while True:
data = raw_input("> ")
s.send(data)
if data == "quit":
break
s.close()
if __name__ == "__main__":
main()
server.py:
from multiprocessing import Process
from os import getpid
import socket
def receive(conn):
print "(%d) connected." % getpid()
while True:
data = conn.recv(1024)
if data:
if data == "quit":
break
else:
print "(%s) data" % getpid()
def main():
s = socket.socket()
s.bind(("localhost", 5555))
s.listen(1)
while True:
conn, address = s.accept()
print "%s:%d connected." % address
Process(target=receive, args=(conn,)).start()
s.close()
if __name__ == "__main__":
main()
*在Windows上,此代码将在酸洗套接字时引发错误:
File "C:\Python27\lib\pickle.py", line 880, in load_eof
raise EOFError
可能是一个问题。你需要子处理,而不是线程。你能发送或编写一个例子吗?我认为算法是:创建子进程,在每个进程中执行启动方法的代码。但我不明白,如何在进程之间正确地发送数据。是的,我可以写一个例子,但不,我不会。正如您已经了解到的,不同进程之间的通信并不容易,坦率地说,它是复杂的,但是python中有一些模块可以帮助缓解多进程()带来的痛苦