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

时间:2017-08-21 21:10:42

标签: python python-asyncio aiohttp

我创建了一个程序,作为浏览器和硬件之间的代理。浏览器以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()

0 个答案:

没有答案