tornadao打造聊天系统

一、目的

最近晚上闲来无事,就顺便学习了一下python Tornado框架,学完它后,用它来写了一个聊天系统,技术栈主要是tornadao+websocket+bookstrap,实现了登录功能,好友在线状态以及群聊的功能,最后用nginx+supervisor部署起来,下面就我来介绍一下是怎么做的吧

二、效果图

1.登录
在这里插入图片描述

2.聊天界面
在这里插入图片描述

三、核心代码

1.服务端

from datetime import datetime

from tornado.web import RequestHandler, MissingArgumentError
from tornado.websocket import WebSocketHandler
from tornado.log import gen_log


clients = dict()
chat_record = list()
users = list()

class WebsocketChatHandler(WebSocketHandler):

    @property
    def username(self):
        for item in users:
            if item["user_id"] == self.user_id:
                return item["username"]
        return "anonymous"

    def open(self):
        self.user_id = self.get_argument("user_id")
        clients[self.user_id] = {
            "user_id": self.user_id,
            "object": self,
        }
        self.set_user_status()
        self.send_users()
        gen_log.info(f"{self.username}|[{self.user_id}] is chatting")
        # self.send_chat_record()

    def set_user_status(self):
        for user in users:
            if user["user_id"] == self.user_id:
                user["status"] = "online"
                break

    def on_message(self, message):
        global chat_record
        chat_message = {
            "user_id": self.user_id,
            "username": self.username,
            "message": message,
            "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "avatar": avatar,
        }
        chat_record.append(chat_message)
        # 只保存200条聊天记录
        chat_record = chat_record[-200:]
        self.send_multi_message(chat_message)

    def on_close(self):
        # 删除连接对象
        del clients[self.user_id]
        # 用户状态置为离线
        for user in users:
            if user["user_id"] == self.user_id:
                user["status"] = "offline"
                break
        # 刷新用户状态
        self.send_users()
        gen_log.info(f"{self.username}|[{self.user_id}] offline")

    def check_origin(self, origin: str) -> bool:
        return True

    # 发送用户列表
    def send_users(self):
        for key in clients.keys():
            clients[key]["object"].write_message({"data": users, "type": 1})

    # 群聊
    def send_multi_message(self, message):
        for key in clients.keys():
            clients[key]["object"].write_message({"data": message, "type": 3})

2.客户端

function webSocketHandler() {
        var host = window.document.location.host;
        if ("WebSocket" in window) {
            ws = new WebSocket(`ws://${host}/websocket?user_id=${USER_ID}`);
            ws.onopen = function () {
                // connect
            };

            ws.onmessage = function (evt) {
                var data = JSON.parse(evt.data);
                console.log(JSON.parse(evt.data));
                if (data.type === 1) {
                    showUserList(data.data)
                } else if (data.type === 2) {

                } else if (data.type === 3) {
                    addMessage(data.data)
                }

            };

            ws.onclose = function () {
                console.log("quit")
            }
        } else {
            alert("create websocket failed")
        }
    }

    webSocketHandler();

上面代码只粘出了核心的websocket的连接与交互,登录很简单就不贴出来了

三、部署

1.nginx

upstream chat {
    server xxxxx:8888;  
}

server {

    listen 8800;
    #填写绑定证书的域名
    server_name xxxxxx;
    location / {
            proxy_pass http://chat;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            #proxy_read_timeout 180s;
    }
}

2.supervisor

[program:chat]
command=/home/apps/chat/env/bin/python3 main.py
directory=/home/apps/chat/src/
stderr_logfile=/home/apps/chat/logs/chat_err.log
user=chat
stopsignal=QUIT
autorestart=true
loglevel=info
redirect_stderr=true
startsecs=1
stopasgroup=true
killasgroup=true

花了一周时间终于搞定了,开心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值