python3 tornado +js+websoket实现多人聊天

首先先来认识一下websocket:

WebSocket API是下一代客户端-服务器的异步通信方法。该通信取代了单个的TCP套接字,使用ws或wss协议,可用于任意的客户端和服务器程序。 WebSocket目前由W3C进行标准化。WebSocket已经受到Firefox 4、Chrome 4、Opera 10.70以及Safari 5等浏览器的支持。

WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为 Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信。

Ajax技术很聪明的一点是没有设计要使用的方式。WebSocket为指定目标创建,用于双向推送消息。

只专注于客户端的API,因为每个服务器端语言有自己的API。下面的代码片段是打开一个连接,为连接创建事件监听器,断开连接,消息时间,发送消息返回到服务器,关闭连接。

 1 // 创建一个Socket实例
 2 var socket = new WebSocket('ws://localhost:8080');
 3 // 打开Socket
 4 socket.onopen = function(event){
 5 // 发送一个初始化消息
 6 socket.send('I am the client and I\'m listening!');
 7 // 监听消息
 8 socket.onmessage = function(event){
 9 console.log('Client received a message',event);
10 };
11 // 监听Socket的关闭
12 socket.onclose = function(event){
13 console.log('Client notified socket has closed',event);
14 };
15 // 关闭Socket....
16 //socket.close()
17 };

下面是一个完整的实例,加上了对用户的识别,首先是服务器端:

 1 import logging
 2 import tornado.escape
 3 import tornado.ioloop
 4 import tornado.options
 5 import tornado.web
 6 import tornado.websocket
 7 import os.path
 8 import uuid
 9 
10 from tornado.options import define, options
11 
12 define("port", default=8888, help="run on the given port", type=int)
13 
14 
15 class Application(tornado.web.Application):
16 
17     def __init__(self):
18         handlers = [
19             (r"/", MainHandler),
20             (r"/websocket", ChatSocketHandler),
21         ]
22         settings = dict(
23             cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
24             template_path=os.path.join(os.path.dirname(__file__), "templates"),
25             static_path=os.path.join(os.path.dirname(__file__), "static"),
26             xsrf_cookies=True,
27         )
28         tornado.web.Application.__init__(self, handlers, **settings)
29 
30 
31 class MainHandler(tornado.web.RequestHandler):
32 
33     def get(self):
34         self.render("index.html", messages=ChatSocketHandler.cache)
35 
36 
37 class ChatSocketHandler(tornado.websocket.WebSocketHandler):
38     # 放置一个集合, 用来记录开启着的连接.
39     clients = set()
40     cache = []
41     cache_size = 200
42 
43     def allow_draft76(self):
44         # for iOS 5.0 Safari
45         return True
46 
47     @staticmethod
48     # 给每一个客户端发送一个加入的信息。
49     def send_to_all(message):
50         for c in ChatSocketHandler.clients:
51             c.write_message(message)
52 
53     def open(self):
54         print ("打开了新的客户端")
55         ChatSocketHandler.send_to_all(str(id(self)) + ' 加入聊天室!!!')
56         ChatSocketHandler.clients.add(self)
57 
58     def on_close(self):
59         ChatSocketHandler.clients.remove(self)
60 
61     @classmethod
62     def update_cache(cls, chat):
63         cls.cache.append(chat)
64         if len(cls.cache) > cls.cache_size:
65             cls.cache = cls.cache[-cls.cache_size:]
66 
67     @classmethod
68     def send_updates(cls, chat):
69         logging.info("sending message to %d clients", len(cls.clients))
70         for client in cls.clients:
71             try:
72                 client.write_message(str(id(client)) + ':' + chat)
73             except:
74                 logging.error("Error sending message", exc_info=True)
75 
76     def on_message(self, message):
77         logging.info("got message %r", message)
78 
79         ChatSocketHandler.send_updates(message)
80 
81 
82 def main():
83     tornado.options.parse_command_line()
84     app = Application()
85     app.listen(8080)
86     tornado.ioloop.IOLoop.instance().start()
87 
88 
89 if __name__ == "__main__":
90     main()


客户端:

 1 <html>
 2 <head>
 3 <title>Web Socket Client</title>
 4 </head> 
 5 
 6 <body> 
 7 
 8 <script type="text/javascript"> 
 9 
10 var socket; 
11 
12 if (!window.WebSocket) { 
13 
14     window.WebSocket = window.MozWebSocket; 
15 
16 } 
17 
18 // Javascript Websocket Client 
19 
20 if (window.WebSocket) { 
21 
22     socket = new WebSocket("ws://localhost:8080/websocket"); 
23 
24     socket.onopen = function(event) { 
25 
26         var ta = document.getElementById('responseText'); 
27 
28         ta.innerHTML = "Web Socket 打开!"; 
29 
30 }; 
31     socket.onmessage = function(event) { 
32 
33         var ta = document.getElementById('responseText'); 
34 
35         ta.innerHTML = ta.innerHTML + "<br>" + event.data ;
36 
37     }; 
38 
39     socket.onclose = function(event) { 
40 
41         var ta = document.getElementById('responseText'); 
42 
43         ta.innerHTML = ta.innerHTML + "Web Socket 关闭!"; 
44 
45     }; 
46 
47 } else { 
48 
49     alert("您的浏览器不支持 Web Socket."); 
50 
51 } 
52 // Send Websocket data 
53 
54 function send() { 
55     var message = document.getElementById("message").value;
56     if (!window.WebSocket) { return; }
57     if (socket.readyState == WebSocket.OPEN) { 
58 
59         socket.send(message); 
60 
61     } else { 
62 
63         alert("socket 没有打开."); 
64 
65     } 
66 } 
67     document.keydown = function (evt){
68         var evt = windown.event?window.event:evt;
69         if(evt.keyCode == 13){
70             send();
71         }
72 }
73 
74 </script> 
75 
76 <h4>接收消息 :</h4> 
77 
78 <div id="responseText" style="width:500px;height:300px;border:2px solid gray"></div> 
79 <h4>发送消息 :</h4> 
80 
81 <input type="text" id="message" name="message" value=""  placeholder="说点什么吧!!!"/>
82 <input type="button" value="发送" onclick="send()" /> 
83 
84 </body> 
85 
86 </html> 

总结:虽然实现以后觉得是很简单的,但是过程是很享受的。

 

posted @ 2015-12-01 15:20  纸鸢&红豆·绿豆  阅读(1620)  评论(0编辑  收藏  举报