tornado与websocket以及2个“聊天室程序”

2个聊天室程序demo

在我的码云:https://gitee.com/huoyingwhw/chatRoom

websocket可以参考另外一篇文章

你真的了解WebSocket吗?

websocket介绍

  WebSocket是HTML5规范中新提出的客户端-服务器通讯协议,协议本身使用新的ws://URL格式。

  WebSocket 是独立的、创建在 TCP 上的协议,和 HTTP 的唯一关联是使用 HTTP 协议的101状态码进行协议切换,使用的 TCP 端口是80,可以用于绕过大多数防火墙的限制。

  WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,两者之间可以创建持久性的连接,并允许数据进行双向传送。

目前常见的浏览器如 Chrome、IE、Firefox、Safari、Opera 等都支持 WebSocket,同时需要服务端程序支持 WebSocket。

tornado中的websocket模块

  Tornado 在 websocket 模块中提供了一个 WebSocketHandler 类。这个类提供了和已连接的客户端通信的 WebSocket 事件和方法的钩子。当一个新的 WebSocket 连接打开时,open 方法被调用,而 on_message 和 on_close 方法分别在连接接收到新的消息和客户端关闭时被调用。

  Tornado提供支持WebSocket的模块是tornado.websocket,其中提供了一个WebSocketHandler类用来处理通讯。

WebSocketHandler.open()

  当一个WebSocket连接建立后被调用。

WebSocketHandler.on_message(message)

  当客户端发送消息message过来时被调用,注意此方法必须被重写

WebSocketHandler.on_close()

  当WebSocket连接关闭后被调用。

WebSocketHandler.write_message(message, binary=False)

  向客户端发送消息messagea,message可以是字符串或字典(字典会被转为json字符串)。若binary为False,则message以utf8编码发送;二进制模式(binary=True)时,可发送任何字节码。

WebSocketHandler.close()

  关闭WebSocket连接。

WebSocketHandler.check_origin(origin)

  判断源origin,对于符合条件(返回判断结果为True)的请求源origin允许其连接,否则返回403。可以重写此方法来解决WebSocket的跨域请求(如始终return True)。

前端JavaScript的编写

在前端JS中使用WebSocket与服务器通讯的常用方法如下:

var ws = new WebSocket("ws://127.0.0.1:8888/websocket"); // 新建一个ws连接
ws.onopen = function() {  // 连接建立好后的回调
   ws.send("Hello, world");  // 向建立的连接发送消息
};
ws.onmessage = function (evt) {  // 收到服务器发送的消息后执行的回调
   alert(evt.data);  // 接收的消息内容在事件参数evt的data属性中
};

在线聊天室的小Demo

项目的目录结构

 

后端代码 server.py

# coding:utf-8

import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
import os
import datetime

from tornado.web import RequestHandler
from tornado.options import define, options
from tornado.websocket import WebSocketHandler

define("port", default=8009, type=int)

class IndexHandler(RequestHandler):
    def get(self):
        self.render("index1.html")

class ChatHandler(WebSocketHandler):

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

    def open(self):
        self.users.add(self)  # 建立连接后添加用户到容器中
        for u in self.users:  # 向已在线用户发送消息
            u.write_message(u"[%s]-[%s]-进入聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

    def on_message(self, message):
        for u in self.users:  # 向在线用户广播消息
            u.write_message(u"[%s]-[%s]-说:%s" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))

    def on_close(self):
        self.users.remove(self) # 用户关闭连接后从容器中移除用户
        for u in self.users:
            u.write_message(u"[%s]-[%s]-离开聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

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

if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([
            (r"/", IndexHandler),
            (r"/chat", ChatHandler),
        ],
        static_path = os.path.join(os.path.dirname(__file__), "static"),
        template_path = os.path.join(os.path.dirname(__file__), "templates"),
        debug = True
        )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

templates目录中index1.html文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>聊天室</title>
</head>
<body>
    <div id="contents" style="height:500px;overflow:auto;"></div>
    <div>
        <textarea id="msg"></textarea>
        <a href="javascript:;" onclick="sendMsg()">发送</a>
    </div>
    <script src="{{static_url('jquery-2.1.4.min.js')}}"></script>
    <script type="text/javascript">
     var ws
= new WebSocket("ws://127.0.0.1:8009/chat"
); ws.onmessage = function(e) { $("#contents").append("<p>" + e.data + "</p>"); }; function sendMsg() { var msg = $("#msg").val(); ws.send(msg); $("#msg").val(""); } </script> </body> </html>

~

posted on 2019-12-11 16:55  江湖乄夜雨  阅读(304)  评论(0编辑  收藏  举报