暸解 WebSocketHandler:
Tornado 提供了一個 WebSocket 模組,我們將透過其中的 WebSocketHandler 來與 WebSocket 互動,有三個函式需要稍微暸解:open()、on_message( )、on_close( )。當 Client 端開啟一個 WebSocket 時,open( ) 將會被執行,on_message( ) 而是接收到訊息時會執行,on_close( ) 則是在連線關閉時會執行。
實作 WebSocketHandler:
首先,我們建立一個名為 server.py 的檔案,接著在裡面建立我們 Server 端的內容:
#!/usr/bin/env/ python
import os
from tornado import web, ioloop, websocket
from tornado.options import define, options
define("ip", default="your.ip")
define("port", default=8888)
# 此物件將記錄並管理所有連線
class ChatManager(object):
users = []
@classmethod
def add_user(cls, websocket):
cls.users.append(websocket)
@classmethod
def remove_user(cls, websocket):
cls.users.remove(websocket)
# 輸出聊天室 UI 畫面
class Chat(web.RequestHandler):
def get(self):
self.render("chat.html")
# 利用 WebSocketHandler 來與 Client 端互動
class Socket(websocket.WebSocketHandler):
def open(self):
# 完成連線,將此 WebSocket 儲存
print ' [x] connected.'
ChatManager.add_user(self)
def on_close(self):
# 連線結束,將此 WebSocket 移除
print ' [x] disconnected.'
ChatManager.remove_user(self)
def on_message(self, message):
# 當有訊息進來時,將此訊息發送給其他 WebSocket
print ' [x] send message.'
for user in ChatManager.users:
user.write_message(message)
# 相關設定參數
settings = dict(
debug=True,
autoreload=True,
compiled_template_cache=False,
static_path=os.path.join(os.path.dirname(__file__), "static"),
template_path=os.path.join(os.path.dirname(__file__), "templates")
)
class Application(web.Application):
def __init__(self):
handlers = [
(r"/", Chat),
(r"/socket", Socket)
]
web.Application.__init__(self, handlers, **settings)
def main():
options.parse_command_line()
app = Application()
app.listen(options.port, options.ip)
ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
實作 WebSocket:
Client 端的實作,主要是使用 HTML5 提供的方式,所以不需要額外的套件,只需要支援 WebSocket 的瀏覽器即可。建立檔案 templates/chat.html。關於 WebSocket 更詳細資訊請參考 HTML5 文件,這邊就不再贅述了,直接看程式內容:
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.msg-box {
border: 1px solid #ddd;
width: 500px; height: 300px;
overflow-y: scroll;
}
</style>
</head>
<body>
<!-- UI -->
<input id="msg-input" type="text" value=""/>
<input id="msg-btn" type="button" value="Send"/><br/><br/>
<!-- Messages -->
<div id="msg-box" class="msg-box"></div>
<script src="/static/jquery-1.11.3.js"></script>
<script>
var chatObj = {
host: location.host,
socket: null,
// 開啟一個 WebSocket 連線,並設定相關動作
init: function(){
var url = "ws://" + chatObj.host + "/socket";
chatObj.socket = new WebSocket(url);
chatObj.socket.onmessage = function(event){
chatObj.showMsg(event.data);
},
chatObj.socket.onclose = function(event){
console.log("on close");
},
chatObj.socket.onerror = function(event){
console.log("on error");
}
},
// 發送訊息至 Server 端
sendMsg: function(){
var msg_input = $("#msg-input")
chatObj.socket.send(msg_input.val());
msg_input.val("").select();
},
// 顯示訊息
showMsg: function(message){
$("#msg-box").append(message + "<br/>");
}
};
$(function(){
var btn = $("#msg-btn");
// 綁定按鈕 click 時發送訊息
btn.click(function(){
chatObj.sendMsg();
return false;
});
$("#msg-input").select();
chatObj.init();
});
</script>
</body>
</html>
最後,專案檔案的配置如下:
├── Tornado-websocket
├── server.py
├── static
│ └── jquery-1.11.3.js
└── templates
└── chat.html
以上工作都完成後,開啟多個瀏覽器分頁並連至 http://your-ip:8888/,分別的在不同的地方輸入文字訊息,就可以看到其他頁面自動同步的狀況了。
Environment :
・ Arch Linux
・ Python 2.7
Reference :
・ Tornado