使用Tornado搭建简单的WebSocket

什么是WebSocket?

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。
WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通信的)远程主机之间进行全双工通信。用于此的安全模型是Web浏览器常用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、需要和服务器进行双向通信的(服务器不能依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或<iframe>和长轮询))应用程序提供一种通信机制。
长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTTP轮询的滥用: 客户端向主机不断发送不同的HTTP呼叫来进行询问。

这会导致一系列的问题:

1.服务器被迫为每个客户端使用许多不同的底层TCP连接:一个用于向客户端发送信息,其它用于接收每个传入消息。

2.有些协议有很高的开销,每一个客户端和服务器之间都有HTTP头。

3.客户端脚本被迫维护从传出连接到传入连接的映射来追踪回复。

一个更简单的解决方案是使用单个TCP连接双向通信。 这就是WebSocket协议所提供的功能。 结合WebSocket API ,WebSocket协议提供了一个用来替代HTTP轮询实现网页到远程主机的双向通信的方法。

WebSocket协议被设计来取代用HTTP作为传输层的双向通讯技术,这些技术只能牺牲效率和可依赖性其中一方来提高另一方,因为HTTP最初的目的不是为了双向通讯。(获得更多关于此的讨论可查阅RFC6202)

实现原理

在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” 。在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:

  1. Header

互相沟通的Header是很小的-大概只有 2 Bytes

  1. Server Push

服务器的推送,服务器不再被动的接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。

python后台代码
1.首先要搭建一个服务器,使用tornado搭建服务器代码如下,搭建服务器代码如有不明请留言
2.使用增加2个Handler
MainHandler:用来实现控制页面跳转到websocket主页
WSHandler:用来控制接受前端websocket的逻辑
其中WSHandler需要继承tornado.websocket.WebSocketHandler对象,并重写open,on_message,on_close
关键是on_message方法,是处理消息到来时候的逻辑
内置write_message是往前端发送数据使用的方法.
#-*-coding:utf-8-*-
from tornado.websocket import WebSocketHandler
from tornado.web import RequestHandler
from tornado import ioloop,httpserver,web
from tornado.options import define,optionsdefine('port',default='6666',help='run port',type=int)
define('runserver',default=True,help='run server',type=bool)
​
class WSHandler(WebSocketHandler):
    users=set()
    def open(self):
        WSHandler.users.add(self)
        print('connected')
    def on_message(self, message):
        print(self.request.remote_ip,message)
        for u in self.users:
            u.write_message('[%s]:%s'%(self.request.remote_ip,message))
    def on_close(self):
        print('8888')
        WSHandler.users.remove(self)
class MainHandler(RequestHandler):
    def get(self):
        self.render('websocket.html')
​
​
handlers=[
    (r'/ws',WSHandler),
    (r'/',MainHandler),
]
​
if __name__ == '__main__':
    options.parse_command_line()
    if options.runserver:
        app=web.Application(handlers=handlers,debug=True,template_path='../templates')
        httpser=httpserver.HTTPServer(app)
        httpser.listen(options.port)
        print('running...')
        ioloop.IOLoop.instance().start()

前端代码

1.前端主要的问题就是引用WebSocket对象,并初始化传入的地址
2.前端同样需要定义3个方法:onopen,onmessage,onclose对应后端的open,on_message,on_close
3.发送消息使用send方法
        var ws=new WebSocket('ws://127.0.0.1:6666/ws');
        ws.onopen=function(){
            $('.status').html('已连接服务器');
        };
        ws.onmessage=function(mes){
            $('.ul').append('<li>'+ mes.data +'</li>');
​
        };
        ws.onclose=function(){
             $('.status').html('连接已断开');
        };
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket</title>
    <script src="http://cdn.static.runoob.com/libs/jquery/1.9.0/jquery.js"></script>
    <style>
​
        .main{
            width: 500px;
            height: 300px;
            border: 1px solid red;
            border-radius: 5px;
            margin: 100px auto;
        }
        .status{
            position: relative;
            text-align: center;
            border: 1px dashed grey;
            height: 38px;
        }
        .bottom{
            margin-bottom: 0px;
            height: 25px;
        }
        .send{
            width: 100%;
            height: 100%;
            border: none;
            background-color: palevioletred;
            font-size: 14px;
            font-family: "Microsoft Yahei";
            color: whitesmoke;
            border-radius: 5px;
        }
        .down{
            height: 25px;
        }
        .ul{
            height: 60%;
        }
    </style>
</head>
<body><h1 align="center">WebSocket聊天室</h1>
<div class="main">
    <div class="status"></div>
    <ul class="ul"></ul>
    <div class="down"><input class="input" type="text" size="79" placeholder="请输入"></div>
    <div class="bottom"><button class="send" >发送信息</button></div>
</div><script>
    $(function(){
        var ws=new WebSocket('ws://127.0.0.1:6666/ws');
        ws.onopen=function(){
            $('.status').html('已连接服务器');
        };
        ws.onmessage=function(mes){
            $('.ul').append('<li>'+ mes.data +'</li>');
​
        };
        ws.onclose=function(){
             $('.status').html('连接已断开');
        };
​
        $('.send').on('click',function(){
          ws.send( $('.input').val());
            $('.input').val('');
        })
        $('.input').bind('keypress',function(event){
            if(event.keyCode=="13"){
                event.preventDefault();
                ws.send( $('.input').val());
                 $('.input').val('');
            }
        })
    })
</script>
</body>
</html>
其它框架(例如Django)后续陆续更新,如果有需要的话……

 

 

赞(0)
未经允许不得转载:http://www.yueguangzu.net逗逗网 » 使用Tornado搭建简单的WebSocket
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址