异步:在循环运行时启动和停止TCP服务器

2024-09-22 18:30:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个程序来充当浏览器和硬件之间的代理。浏览器以websocket的形式启动连接。然后,程序使用初始请求中指定的端口启动TCP服务器。一旦外部设备连接到TCP服务器,它就可以向浏览器发送数据。这个代码示例到目前为止还可以工作,但是我还需要程序关闭TCP服务器和所有连接(如果有任何连接关闭的话)。另一个websocket请求应该再次启动该进程。在

我似乎没有正确地停止服务器/websocket,因为系统将不允许从浏览器进行任何websocket连接(连接被拒绝)。但是,所有其他处理程序仍将在http服务器上响应。在

import aiohttp
from aiohttp import web
import asyncio

def TCPServerFactory(conns):
    def _f(*args,**kwargs):
        return TCPServer(conns,*args,**kwargs)
    return _f

async def sendWS(conn,data):
    await conn.send_str(data) 

class TCPServer(asyncio.Protocol):
    def __init__(self,conns,*args,**kwargs):
        self.conns=conns
        super().__init__(*args,**kwargs)

    def connection_made(self,transport):
        self.transport=transport
        self.conns['tcp']=transport

    def data_received(self,data):
        asyncio.ensure_future(sendWS(self.conns['ws'],data.decode()))

    def connection_lost(self,exc):
        self.conns['ws'].close()

async def sendTCP(conn,data):
    await conn.write(data)

async def wsHandler(request):
    ws=web.WebSocketResponse()
    await ws.prepare(request)

    #Setup TCP server
    loop=asyncio.get_event_loop()
    conns={'ws':ws,'tcp':None}
    try:
        serv=await loop.create_server(TCPServerFactory(conns),'127.0.0.1',8000)
    except:
        await ws.close()
        return ws
    conns['tcpServ']=serv

    async for msg in ws:
        if msg.type==aiohttp.WSMsgType.TEXT:
            if msg.data:
                try:
                    conns['tcp'].write(bytes(msg.data,'utf-8'))
                except:
                    break
        elif msg.type==aiohttp.WSMsgType.CLOSING:
            break
        else:
            break
    try:
        conns['tcp'].close()
    except:
        pass
    serv.close()
    await serv.wait_closed()
    await ws.close()
    return ws

async def handleTCP(request):
    return web.Response(text='TCP worked',headers={'Access-Control-Allow-Origin':'*'})

async def handleHome(request):
    return web.FileResponse(r'c:\workspace\lserver\lserver\test.html')

class HttpServer:
    def start(self):
        asyncio.set_event_loop(asyncio.ProactorEventLoop())
        self.loop=asyncio.get_event_loop()
        self.app=web.Application()
        self.app.router.add_get('/tcp',wsHandler)
        self.app.router.add_get('/',handleHome)
        web.run_app(self.app,host='0.0.0.0',port=8080)
        self.loop.close()

http=HttpServer()
http.start()

Tags: self服务器loopwebasyncioclosedataasync