Stay Hungry,Stay Foolish!

websocket and fastapi

 

This project demonstrates how to use socket.io with FastAPI and React

https://github.com/jrdeveloper124/socketio-app/tree/main

 

You can use WebSockets with FastAPI.

https://fastapi.tiangolo.com/advanced/websockets/

https://stackoverflow.com/questions/71827145/broadcasting-a-message-from-a-manager-to-clients-in-websocket-using-fastapi

 

How to send messages from server to client in a Python WebSockets server, AFTER initial handshake?

https://stackoverflow.com/questions/74988529/how-to-send-messages-from-server-to-client-in-a-python-websockets-server-after

import asyncio
import datetime
from typing import Iterator
import websockets
import random

websocket_connections = set()
sock_port = 8000
sock_url = 'localhost'
global_socket = lambda: None

async def register(websocket):
    print('register event received')
    websocket_connections.add(websocket) # Add this client's socket
    global_socket = websocket

async def poll_log():
    await asyncio.sleep(0.3) # Settle
    while True:
        await asyncio.sleep(0.3) # Slow things down
        
        # Send a dynamic message to the client after random delay
        r = random.randint(1, 10)
        if (r == 5): # Only send 10% of the time
            a_msg = "srv -> cli: " + str(random.randint(1,10000))
            print("sending msg: " + a_msg)
            websockets.broadcast(websocket_connections, a_msg) # Send to all connected clients
        
async def main():
    sock_server = websockets.serve(register, sock_url, sock_port)
    await asyncio.sleep(0.3) # Start up time
    async with sock_server: await poll_log()

if __name__ == "__main__":
    print("Websockets server starting up ...")
    asyncio.run(main())

 

websocket-example

https://github.com/ustropo/websocket-example/tree/main

 

Scaling WebSocket applications

https://unfoldai.com/fastapi-and-websockets/

通过http post API发送数据到websocket数据通道,达到客户端。

import aioredis
from fastapi import FastAPI, WebSocket

app = FastAPI()

async def get_redis():
    redis = await aioredis.create_redis_pool("redis://localhost")
    return redis

@app.websocket("/ws/redis/{channel}")
async def websocket_endpoint(websocket: WebSocket, channel: str):
    await websocket.accept()
    redis = await get_redis()
    try:
        channel = await redis.subscribe(channel)
        async for message in channel[0].iter():
            await websocket.send_text(message.decode())
    finally:
        await redis.unsubscribe(channel)
        redis.close()
        await redis.wait_closed()

@app.post("/publish/{channel}")
async def publish(channel: str, message: str):
    redis = await get_redis()
    await redis.publish(channel, message)
    return {"message": "Published"}

 

 上面使用redis做消息中介, 来链接 HTTP api 和 websocket数据通道。

下面这个例子展示了,使用异步消息队列也是一种可行方案。

https://github.com/fanqingsong/fastapi-websockets-aiohttp-demo

import asyncio

import uvicorn
from fastapi import FastAPI, WebSocket

from client import WebClient
from weather import WeatherClient

client = WebClient()
api = FastAPI()


@api.on_event('shutdown')
def shutdown():
    client.shutdown()


@api.get("/")
async def read_root():
    return {"Hello": "World"}


async def send_weather_data(websocket: WebSocket, weather_client: WeatherClient, data: dict):
    while True:
        weather = await weather_client.weather(data)
        await websocket.send_json(weather.dict())
        await asyncio.sleep(15)


@api.websocket("/ws/weather")
async def read_websocket(websocket: WebSocket):
    await websocket.accept()

    weather_client = WeatherClient(client)
    queue = asyncio.queues.Queue()

    async def read_from_socket():
        async for data in websocket.iter_json():
            queue.put_nowait(data)

    async def send_data():
        data = await queue.get()
        send_task = asyncio.create_task(send_weather_data(websocket, weather_client, data))
        while True:
            data = await queue.get()
            if data:
                print(f'Cancelling existing task since got new event={data}')
                send_task.cancel()
            send_task = asyncio.create_task(send_weather_data(websocket, weather_client, data))

    await asyncio.gather(read_from_socket(), send_data())


if __name__ == '__main__':
    uvicorn.run(api)

 

 

useEffect

https://www.ruanyifeng.com/blog/2020/09/react-hooks-useeffect-tutorial.html

 

posted @ 2024-12-04 23:07  lightsong  阅读(2)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel