一、客戶端代碼 test.html
用於模擬websocket 發送數據請求(新建html文件,粘貼如下代碼,並用谷歌瀏覽器打開)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.wrapper {
margin-top: 16px;
margin-left: 30px;
margin-bottom: 16px;
}
#addressBox {
width: 400px;
height: 30px;
}
.paramsLabel {
margin-left: 30px;
}
#paramsBox {
margin-left: 80px;
}
#sendBtn {
margin-left: 30px;
}
#viewBox {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="wrapper">
<label for="addressBox">socket地址</label>
<input id="addressBox" type="text" value="ws://127.0.0.1:8000/debug/websocket" />
</div>
<label class="paramsLabel" for="paramsBox">socket參數</label>
<div class="wrapper">
<textarea id="paramsBox" cols="30" rows="10" placeholder="請輸入json數據"></textarea>
</div>
<button id="sendBtn">發送請求</button>
<button id="closeBtn">關閉請求</button>
<!-- 展示返回數據 -->
<div id="viewBox" class="wrapper"></div>
<script type="text/javascript">
const addressBox = document.querySelector('#addressBox')
const sendBtn = document.querySelector('#sendBtn')
const paramsBox = document.querySelector('#paramsBox')
const closeBtn = document.querySelector('#closeBtn')
const viewBox = document.querySelector('#viewBox')
var ws = null
// 發送數據
sendBtn.onclick = () => {
var socket = addressBox.value
ws = new WebSocket(socket)
const params = paramsBox.value
console.log(params)
// 打開socket
ws.onopen = function() {
if (params) {
ws.send(params)
} else {
ws.send(JSON.stringify({}))
}
}
// 接收數據
ws.onmessage = function(data) {
viewBox.innerHTML = ''
viewBox.innerHTML += JSON.stringify(data)
}
}
// 關閉socket
closeBtn.onclick = () => {
ws.close(1000,2)
ws.onclose = () => {
console.log('關閉連接')
}
}
</script>
</body>
</html>
二、服務端
採用tornado websocket 自帶的類,處理ws請求;需改寫WebSocketHandler 中的on_message通信方法
import time
import tornado.web
import tornado.websocket
from tornado.ioloop import IOLoop
from tornado import gen
import tornado.options
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
class ExecutorBase(object):
executor = ThreadPoolExecutor(4)
class DebugWebsocket(tornado.websocket.WebSocketHandler, ExecutorBase):
def check_origin(self, origin):
"""校驗權限"""
return True
def open(self):
"""開啓連接"""
print("WebSocket opened")
@gen.coroutine
def on_message(self, message):
"""連接通信"""
request_data = message
resp = yield self.resp_time(request_data)
self.write_message('resp:%s' % resp)
def on_close(self):
"""關閉連接"""
print("WebSocket closed")
@run_on_executor
def resp_time(self, request_data):
# 異步執行延時操作 to do sth
time.sleep(2)
return time.time()
def make_app():
"""路由"""
tornado.options.parse_command_line()
return tornado.web.Application([
(r"/debug/websocket", DebugWebsocket),
])
def start(port):
"""啓動"""
app = make_app()
app.listen(port=port)
IOLoop.current().start()
if __name__ == '__main__':
print('--start--')
start(8000)