1 Star 1 Fork 0

JOHNSON / async-socket

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
server.py 5.42 KB
一键复制 编辑 原始数据 按行查看 历史
JOHNSON 提交于 2020-11-09 20:03 . fix some bugs
import socket
import asyncio
import threading
import functools
from utils import logging
from handler import BaseHandler
class TCPServer(object):
def __init__(self, server_address: tuple, handler_cls):
self.server_address = server_address
self.handler_cls = handler_cls
self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__socket.bind(self.server_address)
self.__socket.listen(5)
self.__loop: asyncio.AbstractEventLoop = asyncio.get_event_loop()
# 用于睡眠线程
self.th_event = threading.Event()
# 是否关闭状态
self.__is_shutdown: bool = True
# 客户端列表, 存在字典里 key 是客户端地址, value 是对应的客户端 handler 实例
self.client_list: dict = {}
# 发送列表
self.send_list: list = []
def run_server(self):
self.th_event.clear()
self.__is_shutdown = False
try:
threading.Thread(target=lambda: self.__loop.run_until_complete(self.__run())).start()
except Exception:
pass
async def __run(self):
logging.info("服务器运行在 {}:{}".format(self.server_address[0], self.server_address[1]))
while not self.__is_shutdown:
client, remote_address = await self.__loop.sock_accept(self.__socket)
self.__loop.create_task(self.on_connection(client, remote_address))
async def on_connection(self, client: socket.socket, remote_address: tuple):
handler: BaseHandler = self.handler_cls(self, client, remote_address)
self.client_list["%s:%d" % (remote_address[0], remote_address[1])] = handler
while handler.is_connection:
try:
data: bytes = await self.__loop.sock_recv(client, handler.recv_len)
except ConnectionResetError:
"""
异常处理, ConnectionResetError 远程主机主动断开连接
该异常是对方主动与我方断开连接,
"""
handler.on_connect_err('ConnectionResetError', descriotion="远程主机主动断开连接")
break
except ConnectionAbortedError:
"""
异常处理, ConnectionAbortedError 你的主机中软件终止了一个已建立的连接
该异常是我方主动与对方断开连接,
"""
handler.on_connect_err('ConnectionAbortedError', descriotion="你的主机中软件终止了一个已建立的连接")
break
except:
"""
异常处理, 奇奇怪怪的异常处理,
该异常处理其他异常
"""
handler.on_connect_err('OtherError', descriotion="异常处理, 奇奇怪怪的异常处理")
return None, True
handler.on_message(data)
return False
def send(self, data_type:str, data: str, target = None):
"""
发送消息
:param data_type:
:param data:
:param target:
:return:
"""
# 先判断目标是不是空, 是空为广播
if target is None:
for key in list(self.client_list):
client: BaseHandler = self.client_list[key]
try:
client.send(data_type, data)
except Exception:
client.close_connnect()
del self.client_list[key]
# 指定目标就发送给指定客户端
else:
client = self.client_list[target]
try:
client.send(data_type, data)
except Exception:
del self.client_list[target]
def on_disconnection(self, remote_address: tuple):
logging.error("Lost connection.")
del self.client_list["%s:%d" % (remote_address[0], remote_address[1])]
def close(self):
self.__is_shutdown = True
self.th_event.wait()
self.client_list.clear()
@property
def is_run(self):
return not self.__is_shutdown
class SimpeHandler(BaseHandler):
def handle(self, data_type, data):
logging.info(
"Received {host}: {data}".format(host="%s:%d" % (self.remote_address[0], self.remote_address[1]),
data=data))
if __name__ == '__main__':
server = TCPServer(server_address=("127.0.0.1", 8080), handler_cls=SimpeHandler)
server.run_server()
while server.is_run:
data = input()
if data == "show client":
print(server.client_list)
elif data[:13] == "select client":
key = data[13:].strip()
try:
client = server.client_list[key]
except KeyError:
logging.error("No corresponding D was found.")
continue
server.send_list.append(client)
logging.info("Selected client %s." % key)
elif data[:13] == "show selected":
print(server.send_list)
elif data[:9] == "send data":
pkt = data[9:].strip()
_type, content = pkt.split(":")
if len(server.send_list) <= 0:
logging.error("Send list to be empty")
for client in server.send_list:
client.send(_type, content)
logging.info("Sended.")
elif data == "exit":
server.close()
break
Python
1
https://gitee.com/J0hNs0N/async-socket.git
git@gitee.com:J0hNs0N/async-socket.git
J0hNs0N
async-socket
async-socket
master

搜索帮助