web的实时推送技术--websocket

Python的tornado框架中,websocket允许浏览器和服务器之间进行双向,实时,持久的,全双工通信。协议本身使用 ws://URL的格式,如果是加密的websocket则使用的是wss://URL

websocket的起源

websocket和其他方式的比较:
1、http协议中的”keep-alive connection”,是指一次tcp连接中完成多个http请求,但对每个请求依然要单独发header;
2、轮询(Polling),是指从客户端(一般就是浏览器)不断主动的向服务器http请求查询是否有新数据;
3、Comet技术,Comet技术又细分为两种实现方式:一种是长轮询机制,一种是流技术;
这几种方式具有很明显的缺点,就是需要由浏览器对服务器发出http request,大量消耗服务器的带宽和资源(就是除了真正的数据部分外,服务器和客户端还要大量交换http header,信息交换率很低),为了解决这种状况,Websocket能够更好的节省服务器资源和带宽并实现真正意义上的实时推送;
websocket的优点:
1、websocket是独立的,建立在tcp上的协议,和http协议唯一的关联就是使用http协议的101状态码进行协议切换,使用的tcp端口是80,可以用于绕过大多数防火墙的限制;
2、websocket使得客户端和服务器之间的数据交换变得更加简单,允许服务器端直接向客户端推送数据而不需要客户端进行请求;
3、websocket的客户端和服务器之间可以创建持久性的连接,并允许数据进行双向传送;
websocket协议与http协议的联系:
websocket和http协议一样,都是基于tcp的,所以websocket也是一种可靠的协议,Web开发者调用的websocket的send()函数在browser(浏览器)的实现最终都是通过tcp的系统接口进行传输的。
websocket和http协议一样都是应用层的协议,websocket在建立握手连接时,数据是通过http协议传输的,但是在建立连接之后,真正的数据传输阶段是不需要http协议参与的。
下图是协议栈中的websocket和http的关系:

web的实时推送技术--websocket_第1张图片

tornado的websocket模块:
1、在使用时应该添加 from tornado.websocket import WebSocketHandler,或者要导入tornado的以下几个包

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

WebSocketHandler类,这个类提供了和已连接的客户端进行通信的WebSocket通信的事件和钩子;
2、WebSocketHandler.open()
当一个WebSocket连接建立后被调用;
3、WebSocketHandler.on_message(message)
当客户端发送消息message过来时被调用,此方法必须重写;
4、WebSocketHandler.on_close()
当WebSocket连接关闭后被调用;
5、WebSocketHandler.write_message(message,binary=False)
向客户端发送消息message,message可以是字符串或字典(字典会被转为json字符串);binary是False,则message以utf8编码的形式发送;binary=True,message可以发送任何字节码;
6、WebSocketHandler.close()
关闭websocket连接
7、WebSocketHandler.check_origin(origin)
重写此方法可以解决websocket的跨域请求;判断源origin,对于符合条件(返回结果为True)的请求源origin允许其连接,否则返回403;

//支持跨域请求
def check_origin(self, origin):
    return True
//允许所有子域下的连接
def check_origin(self, origin):
    parsed_origin = urllib.parse.urlparse(origin)
    return parsed_origin.netloc.endswith(".mydomain.com")

websocket客户端的常见API:
1、WebSocket构造函数,用于新建一个WebSocket实例,当执行下列语句之后,客户端就会与服务器进行连接;

var ws = new WebSocket('ws://localhost:8080/ws');

2、WebSocket.readyState,readyState属性返回实例对象的当前状态,总共有以下四种状态:

CONNECTING:值为0,表示正在连接;
OPEN:值为1,表示连接成功,可以正常通信;
CLOSING:值为2,表示连接正在关闭;
CLOSED:值为3,表示连接已经关闭,或者打开连接失败;

3、WebSocket.onopen,实例对象的open属性,用来指定连接成功后的回调函数;

//ws.send(message),客户端向服务器发送消息
ws.onopen = function (){
   ws.send('Hello Server!');
}

如果用户想要指定多个回调函数,可以使用addEventListener方法;

ws.addEventListener('open',function(event){
  ws.send('Hello Server!');
});

4、WebSocket.onclose,实例对象的onclose属性,用于指定连接关闭后的回调函数;

ws.onclose = function() { 
};

5、WebSocket.onmessage,实例对象的onmessage属性,用于指定收到服务器数据之后的回调函数;

ws.onmessage = function(event){
    var data = event.data;
    //处理数据
};
ws.addEventListener("message",function(event){
    var data = event.data;
    //处理数据
});

6、WebSocket.bufferedAmount,实例对象的bufferedAmount属性,表示还有多少字节的二进制数据没有发送出去,它可以用来判断是否发送结束;

var data = new ArrayBuffer(10000000);
ws.send(data);
if(ws.bufferedAmount == 0){
    //发送结束
}
else{
     //发送未结束
}

7、WebSocket.onerror,实例对象的onerror属性,用于指定报错时候的回调函数;

ws.onerror = function(event){
     //处理错误事件
}
ws.addEventListener("error",function(event){
     //处理错误事件
});

一个简单的关于websocket的例子:
1、程序框架
web的实时推送技术--websocket_第2张图片
2、code

#如何开启服务-->  python2.7 ws_test.py
index.html
 
 <html lang="zh-cn">
 <head>
 <meta charset="UTF-8">
 <title>tornado websocket testtitle>
 head>
 <script type="text/javascript">
    var ws;
    function onLoad(){
         ws = new WebSocket("ws://100.82.23.37:9999/websocket");
         ws.onmessage = function(e){
             alert(e.data)
         }
     }
     function SendMessage(){
         ws.send(document.getElementById('msg').value);
     }
 script>
  <body onload='onLoad();'>
    要发送的消息:<input type="text" id="msg" />
     <input type="button" onclick="SendMessage();" value="提交" />
  body>
html>

ws_test.py

#!/usr/local/bin/python2.7
#-*- encoding:utf-8 -*-

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop

class MyHandlerIndex(tornado.web.RequestHandler):
      def get(self):
          self.render('index.html')

class MyWebSocketHandler(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 is :" + message)
       def on_close(self):
           pass

 class MyHandlerApplication(tornado.web.Application):
       def __init__(self):
           handlers = [
              (r'/', MyHandlerIndex),
              (r'/websocket',MyWebSocketHandler)
           ]
          setting = {'template_path' : 'templates'}      tornado.web.Application.__init__(self,handlers,**setting)

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

3、执行结果

web的实时推送技术--websocket_第3张图片


参考资料:
tornado-websocket-浏览器与服务器双向通信
websocket学习简书
http://www.ruanyifeng.com/blog/2017/05/websocket.html
http://www.giantflyingsaucer.com/blog/?p=4586

你可能感兴趣的:(Python基础)