Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3; Websockets Server & HTTP Server - run_forever & serve_forever

I am trying to run a websockets server and an http server in the same python application. It looks like I'm trying to run two forever loops and the 2nd loop is not getting activated. Any advice on how I can get both of these servers running?

httpd = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler)

httpd.serve_forever()
asyncio.get_event_loop().run_until_complete(
    websockets.serve(echo, 'localhost', 8001))
asyncio.get_event_loop().run_forever()
like image 696
user1898041 Avatar asked Jun 17 '26 17:06

user1898041


1 Answers

Here is one way to serve both websockets and http requests with one server. The only difference with what you proposed is that both handlers listen on the same port.

I reckon it's possible to listen to separate ports by defining two aiohttp applications. However, you will in any case need an asyncio-capable HTTP server. AFAIK HTTPServer is not asyncio-enabled, so your proposed solution cannot work, since you are mixing an asyncio-based server (websockets.serve) with a non-async one (HTTPServer).

#!/usr/bin/python3.7

import aiohttp
from aiohttp import web, WSCloseCode
import asyncio


async def http_handler(request):
    return web.Response(text='Hello, world')


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

    async for msg in ws:
        if msg.type == aiohttp.WSMsgType.TEXT:
            if msg.data == 'close':
                await ws.close()
            else:
                await ws.send_str('some websocket message payload')
        elif msg.type == aiohttp.WSMsgType.ERROR:
            print('ws connection closed with exception %s' % ws.exception())

    return ws


def create_runner():
    app = web.Application()
    app.add_routes([
        web.get('/',   http_handler),
        web.get('/ws', websocket_handler),
    ])
    return web.AppRunner(app)


async def start_server(host="127.0.0.1", port=1337):
    runner = create_runner()
    await runner.setup()
    site = web.TCPSite(runner, host, port)
    await site.start()


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(start_server())
    loop.run_forever()
like image 185
Cosimo Avatar answered Jun 20 '26 06:06

Cosimo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!