基于js/tornado的简单websocket通信

websocket简单介绍

因为web的基础http协议是无状态的,每个http请求都是一个socket短链接,因此只能由客户端向服务端发消息,而服务端不能主动向客户端发消息,服务器需要主动通知客户端的时候就无能为力了,因此诞生了websocket。

websocket只是一种协议,实现这种协议的服务端有很多种,今天我要聊是基于python,tornado框架的实现。->中文文档<-

websocket客户端

基于javascript的客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var ws = new WebSocket("ws://xxx.ylkb.net:8080/ws");

ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};

ws.onclose = function(evt) {
console.log("Connection closed.");
};

websocket服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop

class WebSocketHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True

def open(self):
pass

def on_message(self, message):
self.write_message(u"Your message was: "+message)

def on_close(self):
pass

class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r'/ws', WebSocketHandler)
]
# settings = { "template_path": "."}
settings = {}
tornado.web.Application.__init__(self, handlers, **settings)

if __name__ == '__main__':
ws_app = Application()
server = tornado.httpserver.HTTPServer(ws_app)
server.listen(8080)
tornado.ioloop.IOLoop.instance().start()

其他

  1. 心跳检测,由于websocket本质上是一个tcp的长连接,因此需要检测存活性
  2. 用户权限验证,需要在握手完成以后进行用户auth的操作
  3. 集群方式的用户数据同步,例如一个聊天室人太多,一个服务器扛不住,需要多台
  4. 容量限制,一个server链接的人太多了以后,为了保证已链接用户的服务质量,后面的用户需要排队
  5. 在https的网站里面需要用wss协议,这时候需要用nginx的反向代理做协议转换

以下为nginx的核心配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 10.10.10.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}