python tornado简易ws聊天室测试

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function
from datetime import datetime
import tornado
from tornado.options import define, options
from tornado.websocket import WebSocketHandler
import signal
import sys

# 设置服务器端口
define("port", default=6228, type=int)


class ChatHandler(WebSocketHandler):
    users = set()  # 用来存放在线用户的容器

    def open(self, *args, **kwargs):
        id_param = self.get_argument("id", default=None)
        print(id_param)
        # 建立连接后添加用户到容器中
        self.users.add(self)
        # 向已在线用户发送消息
        for user in self.users:
            remote_ip, port = self.request.connection.context.address
            now = datetime.now().strftime("%H:%M:%S")
            user.write_message("[{}][{}:{}]-进入聊天室".format(now, remote_ip, port))

        # 安排定时发送 ping 消息,毫秒,或者把这个方法提出来,弄成全局的定时器,服务于全部在线人群
        self.heartbeat_callback = tornado.ioloop.PeriodicCallback(
            self.send_heartbeat, 10000
        )
        self.heartbeat_callback.start()

    def on_message(self, message):
        # 向在线用户广播消息
        now = datetime.now().strftime("%H:%M:%S")
        remote_ip, port = self.request.connection.context.address
        for user in self.users:
            user.write_message("[{}][{}:{}] {}".format(now, remote_ip, port, message))

    def on_close(self):
        # 用户关闭连接后从容器中移除用户
        now = datetime.now().strftime("%H:%M:%S")
        remote_ip, port = self.request.connection.context.address
        self.users.remove(self)
        self.heartbeat_callback.stop()
        for user in self.users:
            user.write_message("[{}][{}:{}]-离开聊天室".format(now, remote_ip, port))

    def check_origin(self, origin):
        return True  # 允许WebSocket的跨域请求

    # 发送心跳的方法
    def send_heartbeat(self):
        try:
            # 发送 ping 消息
            self.write_message("ping", binary=False)
        except Exception as e:
            # 如果发送失败,可能是连接已经关闭
            self.users.remove(self)
            self.heartbeat_callback.stop()
            for user in self.users:
                user.write_message("离开聊天室")


def router():
    return tornado.web.Application([
        (r"/ws", ChatHandler),
    ],
        debug=True
    )


def main():
    app = router()

    # 设置信号处理器,优雅地处理 SIGINT 信号
    def signal_handler(sig, frame):
        print('Stopping Tornado web server...')
        tornado.ioloop.IOLoop.current().stop()
        sys.exit(0)

    tornado.options.parse_command_line()
    signal.signal(signal.SIGINT, signal_handler)
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()


if __name__ == "__main__":
    main()

posted @   朝阳1  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示