{"id":8944,"date":"2023-09-13T01:41:45","date_gmt":"2023-09-12T17:41:45","guid":{"rendered":"\/?p=8944"},"modified":"2023-09-13T01:41:45","modified_gmt":"2023-09-12T17:41:45","slug":"fastapi%e5%9f%ba%e7%a1%80%ef%bc%9a8-websocket-%e9%a1%b9%e7%9b%ae%e9%83%a8%e7%bd%b2","status":"publish","type":"post","link":"\/?p=8944","title":{"rendered":"FastAPI\u57fa\u7840\uff1a8.WebSocket &#038; \u9879\u76ee\u90e8\u7f72"},"content":{"rendered":"<h2>WebSocket<\/h2>\n<p><a href=\"https:\/\/fastapi.tiangolo.com\/zh\/advanced\/websockets\/#try-the-websockets-with-dependencies\">WebSockets - FastAPI (tiangolo.com)<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/encode\/broadcaster\">encode\/broadcaster: Broadcast channels for async web apps. \ud83d\udce2 (github.com)<\/a><\/p>\n<p><strong>\u76f4\u63a5\u7528\u7684\u5b98\u65b9\u6587\u6863\u4f8b\u5b50<\/strong>:<\/p>\n<pre><code class=\"language-python\">from uvicorn import run\n\n&quot;&quot;&quot;\nwebsocket\n pip install websockets\n&quot;&quot;&quot;\nfrom fastapi import FastAPI\n\napp = FastAPI(title=&quot;websocket&quot;)\nfrom typing import List\n\nfrom fastapi import FastAPI, WebSocket, WebSocketDisconnect\nfrom fastapi.responses import HTMLResponse\n\nhtml = &quot;&quot;&quot;\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n    &lt;head&gt;\n        &lt;title&gt;Chat&lt;\/title&gt;\n    &lt;\/head&gt;\n    &lt;body&gt;\n        &lt;h1&gt;WebSocket Chat&lt;\/h1&gt;\n        &lt;h2&gt;Your ID: &lt;span id=&quot;ws-id&quot;&gt;&lt;\/span&gt;&lt;\/h2&gt;\n        &lt;form action=&quot;&quot; onsubmit=&quot;sendMessage(event)&quot;&gt;\n            &lt;input type=&quot;text&quot; id=&quot;messageText&quot; autocomplete=&quot;off&quot;\/&gt;\n            &lt;button&gt;Send&lt;\/button&gt;\n        &lt;\/form&gt;\n        &lt;ul id=&#039;messages&#039;&gt;\n        &lt;\/ul&gt;\n        &lt;script&gt;\n            var client_id = Date.now()\n            document.querySelector(&quot;#ws-id&quot;).textContent = client_id;\n            var ws = new WebSocket(`ws:\/\/localhost:8000\/ws\/${client_id}`);\n            ws.onmessage = function(event) {\n                var messages = document.getElementById(&#039;messages&#039;)\n                var message = document.createElement(&#039;li&#039;)\n                var content = document.createTextNode(event.data)\n                message.appendChild(content)\n                messages.appendChild(message)\n            };\n            function sendMessage(event) {\n                var input = document.getElementById(&quot;messageText&quot;)\n                ws.send(input.value)\n                input.value = &#039;&#039;\n                event.preventDefault()\n            }\n        &lt;\/script&gt;\n    &lt;\/body&gt;\n&lt;\/html&gt;\n&quot;&quot;&quot;\n\nclass ConnectionManager:\n    def __init__(self):\n        # \u5b58\u50a8\u7528\u6237\n        self.active_connections: List[WebSocket] = []\n\n    async def connect(self, websocket: WebSocket):\n        # \u8fde\u63a5\u4e8b\u4ef6\n        await websocket.accept()\n        self.active_connections.append(websocket)\n\n    def disconnect(self, websocket: WebSocket):\n        # \u65ad\u5f00\n        self.active_connections.remove(websocket)\n\n    async def send_personal_message(self, message: str, websocket: WebSocket):\n        # \u53d1\u9001\u6d88\u606f\n        await websocket.send_text(message)\n\n    async def broadcast(self, message: str):\n        # \u5149\u64ad\u6d88\u606f\n        for connection in self.active_connections:\n            await connection.send_text(message)\n\nmanager = ConnectionManager()\n\n@app.get(&quot;\/&quot;)\nasync def get():\n    return HTMLResponse(html)\n\n@app.websocket(&quot;\/ws\/{client_id}&quot;)\nasync def websocket_endpoint(websocket: WebSocket, client_id: int):\n    await manager.connect(websocket)\n    try:\n        while True:\n            data = await websocket.receive_text()\n            await manager.send_personal_message(f&quot;You wrote: {data}&quot;, websocket)\n            await manager.broadcast(f&quot;Client #{client_id} says: {data}&quot;)\n    except WebSocketDisconnect:\n        manager.disconnect(websocket)\n        await manager.broadcast(f&quot;Client #{client_id} left the chat&quot;)\n\nif __name__ == &quot;__main__&quot;:\n    # \u542f\u7528web\u670d\u52a1\uff0c reload -&gt; \u5f53\u6539\u53d8\u4ee3\u7801\u65f6\u81ea\u52a8\u91cd\u542f # fastapi_02:app\n    run(&quot;__main__:app&quot;, reload=True)\n<\/code><\/pre>\n<h2>\u6548\u679c<\/h2>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/1670151614321-4ce8424d-b2b7-4a64-842f-f99719897a0e.png\" alt=\"image.png\" \/><\/p>\n<h2>\u90e8\u7f72<\/h2>\n<p><a href=\"https:\/\/github.com\/tiangolo\/uvicorn-gunicorn-fastapi-docker\">tiangolo\/uvicorn-gunicorn-fastapi-docker: Docker image with Uvicorn managed by Gunicorn for high-performance FastAPI web applications in Python with performance auto-tuning. Optionally with Alpine Linux. (github.com)<\/a><\/p>\n<p><a href=\"https:\/\/hub.docker.com\/r\/tiangolo\/uvicorn-gunicorn-fastapi\">https:\/\/hub.docker.com\/r\/tiangolo\/uvicorn-gunicorn-fastapi<\/a><\/p>\n<pre><code class=\"language-dockerfile\">FROM tiangolo\/uvicorn-gunicorn-fastapi:python3.9\nCOPY . \/app\nRUN ln -sf \/usr\/share\/zoneinfo\/Asia\/Shanghai \/etc\/localtime &amp;&amp; \\\n    echo &#039;Asia\/Shanghai&#039; &gt;\/etc\/timezone &amp;&amp; \\\n    pip install --no-cache-dir --upgrade -r requirements.txt -i https:\/\/pypi.tuna.tsinghua.edu.cn\/simple\/<\/code><\/pre>\n<p>ps: \u8fd9\u4e2a\u955c\u50cf\u6700\u7ec8\u4f1a\u6267\u884cmain.py\uff0c\u6240\u4ee5\u4fdd\u8bc1main.py\u5b58\u5728FastAPI \u5b9e\u4f8b, \u5e76\u4e14\u542f\u52a8\u7aef\u53e3\u4e3a 80<\/p>\n<pre><code class=\"language-yaml\">version: &quot;3&quot;\nservices:\n  backend:\n    build:\n      context: .\/\n      # dockerfile\u6587\u4ef6\u540d\n      dockerfile: Dockerfile\n    # \u5bb9\u5668\u540d\u79f0\n    container_name: fastapi-serve\n    # \u7aef\u53e3\u6620\u5c04\n    ports:\n      - &quot;1855:80&quot;<\/code><\/pre>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/1670152546372-118732fa-c721-46ef-8fe3-18d1230ccb4c.png\" alt=\"image.png\" \/><\/p>\n<pre><code class=\"language-shell\">docker-compose up -d<\/code><\/pre>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/1670152653548-fb6cde24-7ed6-4391-a0a6-daf37536e918.png\" alt=\"image.png\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>WebSocket WebSockets &#8211; FastAPI (tiangolo.com) encode\/broadcaster: Br   \u2026 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0},"categories":[204],"tags":[116],"_links":{"self":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8944"}],"collection":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=8944"}],"version-history":[{"count":1,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8944\/revisions"}],"predecessor-version":[{"id":8945,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8944\/revisions\/8945"}],"wp:attachment":[{"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=8944"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=8944"},{"taxonomy":"post_tag","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=8944"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}