IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 基于FastAPi的websocket 实现 一对一的客服demo -> 正文阅读

[网络协议]基于FastAPi的websocket 实现 一对一的客服demo

环境

  • python3.7.6、fastapi、websockets9.1

功能说明

  • 模拟1对1的客服聊天
  • 客户id 聊天记录缓存,关闭窗口后,再次打开相同的客户id,之前聊天记录会再现

代码如下 解释就自己看吧

# -*- coding:utf-8 -*-
# @FileName  :demo.py
# @Time      :2021/7/26 18:09
# @Author    :Ranger
# @Info      :

import uvicorn
from fastapi import FastAPI
from starlette.websockets import WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from typing import List
from datetime import datetime

websocket_ip = 'localhost'

app = FastAPI()

class ChatText:
    def __init__(self,
                 chat_src,
                 chat_text):
        """

        :param chat_src:    0-客户端 1-服务端
        :param chat_text:
        """
        self.chat_src = chat_src
        self.chat_text = chat_text
        self.timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')


class CustomerChatUtils:
    def __init__(self,
                 client_id):
        self.client_id = client_id
        self.server_websocket = None
        self.customer_websocket = None
        self.active = False
        self.timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.chat_message_list: List[ChatText] = []


class CustomerServiceUtils:
    def __init__(self):
        self.client_ids = []
        self.customer_active_connections: List[WebSocket] = []  # 客户端活跃链接
        self.server_active_connections: List[WebSocket] = []  # 服务端活跃链接
        self.customer_chat_obj: List[CustomerChatUtils] = []

    async def customer_connect(self, websocket: WebSocket):
        await websocket.accept()
        self.customer_active_connections.append(websocket)

    async def server_connect(self, websocket: WebSocket):
        await websocket.accept()
        self.server_active_connections.append(websocket)

    def customer_disconnect(self, websocket: WebSocket):
        self.customer_active_connections.remove(websocket)
        for item in self.customer_chat_obj:
            if item.customer_websocket == websocket:
                item.customer_websocket = None
                item.active = False

    def server_disconnect(self, websocket: WebSocket):
        self.server_active_connections.remove(websocket)
        for item in self.customer_chat_obj:
            if item.server_websocket == websocket:
                item.server_websocket = None

    def get_customer_chat_obj(self, client_id) -> CustomerChatUtils:
        """获取历史聊天记录

        :param client_id:
        :return:
        """
        current_chat_message = None
        for chat_message in self.customer_chat_obj:
            if chat_message.client_id == client_id:
                current_chat_message = chat_message
                break
        if current_chat_message is None:
            current_chat_message = CustomerChatUtils(client_id)
            self.customer_chat_obj.append(current_chat_message)
        return current_chat_message


customer_service_utils = CustomerServiceUtils()

@app.get("/chat/client/{client_id}")
async def chat_client(client_id: int):
    html_content = f"""
<!DOCTYPE html>
<html>
    <head>
        <title>客户端</title>
    </head>
    <body>
        <h1>客户端 Chat</h1>
        <form action="" οnsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("ws://{websocket_ip}:8000/ws/customer/{client_id}");
    """ + """
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""
    return HTMLResponse(html_content)


@app.get("/chat/server/{client_id}")
async def chat_server(client_id: int):
    html_content = f"""
<!DOCTYPE html>
<html>
    <head>
        <title>服务端</title>
    </head>
    <body>
        <h1>服务端 Chat</h1>
        <form action="" οnsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("ws://{websocket_ip}:8000/ws/server/{client_id}");
    """ + """
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""
    return HTMLResponse(html_content)


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")


@app.websocket("/ws/customer/{client_id}")
async def websocket_endpoint_customer(websocket: WebSocket, client_id: int):
    await customer_service_utils.customer_connect(websocket)
    try:
        customer_chat_obj = customer_service_utils.get_customer_chat_obj(client_id)
        customer_chat_obj.active = True
        customer_chat_obj.customer_websocket = websocket
        for chat_message in customer_chat_obj.chat_message_list:
            if chat_message.chat_src == 0:
                await websocket.send_text(f'我 {chat_message.timestamp}: {chat_message.chat_text}')
            else:
                await websocket.send_text(f'客服 {chat_message.timestamp}: {chat_message.chat_text}')
        while True:
            data = await websocket.receive_text()
            print(f'客户端发送消息:{data}')
            _chat_text = ChatText(0, data)
            customer_chat_obj.chat_message_list.append(_chat_text)
            await websocket.send_text(f"我 {_chat_text.timestamp}: {data}")
            # 发送给服务端
            if customer_chat_obj.server_websocket is not None:
                await customer_chat_obj.server_websocket.send_text(f"客户{client_id}-{_chat_text.timestamp}: {data}")
    except WebSocketDisconnect:
        customer_service_utils.customer_disconnect(websocket)


@app.websocket("/ws/server/{client_id}")
async def websocket_endpoint_server(websocket: WebSocket, client_id: int):
    await customer_service_utils.server_connect(websocket)
    try:
        customer_chat_obj = customer_service_utils.get_customer_chat_obj(client_id)
        if customer_chat_obj.active:
            customer_chat_obj.server_websocket = websocket
            for chat_message in customer_chat_obj.chat_message_list:
                if chat_message.chat_src == 0:
                    await websocket.send_text(f'客户{client_id}-{chat_message.timestamp}: {chat_message.chat_text}')
                else:
                    await websocket.send_text(f'我 {chat_message.timestamp}: {chat_message.chat_text}')
            while True:
                data = await websocket.receive_text()
                print(f'服务端发送消息:{data}')
                _chat_text = ChatText(1, data)
                customer_chat_obj.chat_message_list.append(_chat_text)
                await websocket.send_text(f"我 {_chat_text.timestamp}: {data}")
                if customer_chat_obj.customer_websocket is not None:
                    await customer_chat_obj.customer_websocket.send_text(
                        f"客服:{_chat_text.timestamp}: {data}")
        else:
            await websocket.send_text("非法的client_id")
    except WebSocketDisconnect:
        customer_service_utils.server_disconnect(websocket)


uvicorn.run(app, host="0.0.0.0", port=8000)

  • 客户端链接 http://localhost:8000/chat/client/{client_id}
  • 比如client_id 为1: http://localhost:8000/chat/client/1
  • 服务端链接 http://localhost:8000/chat/server/{client_id}
  • 比如对接客户id为 1 的服务端链接 http://localhost:8000/chat/server/1

客户端截图

image.png

服务端截图

image.png

如果对你帮助,希望点个赞,谢谢

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-03 11:34:09  更:2021-08-03 11:35:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 13:32:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码