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 协议中,为我们实现即时服务带来了两大好处:
- Header
互相沟通的Header是很小的-大概只有 2 Bytes
- 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,options
define('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('连接已断开');
};
<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)后续陆续更新,如果有需要的话……
最新评论