最近在看客户端与服务器之间的数据交换问题,之前只是知道ajax与WebSocket,知其然不知其所以然,记录一下。
以下为引入菜鸟教程内容,非原创。
1.何为WebSocket
WebSocket是一种在HTML5中提供的在单个TCP连接上建立全双工通信的协议,浏览器和服务器之间只需要完成一次握手,两者就可以进行持久连接,从而完成数据的双向传输。注意:Socket 是传输控制层协议,其实Socket是位于应用层和数据传输层的一组接口,所以会定义为传输控制层协议;而WebSocket 是应用层协议。
为了从服务器获取数据,各种解决方式都是基于HTTP框架完成的,要么定时轮询,要么建立长连接;
传统的Request-Response根本问题在于,请求由客户端发起,服务端进行响应,一旦我们需要服务器主动向客户端发送数据,由于之前建立的TCP连接已经断开,无法识别客户端在哪。现在的很多网站数据推送技术采用Ajax轮询,由浏览器向服务器定期发送HTTP请求,然后从服务器返回最新数据给浏览器,如果HTTP的请求包括较长的头部信息,真正有用的数据非常小,就会造成带宽等资源的浪费;而WebSocket可以更好节省带宽等服务器资源,并且能够完成实时性的通讯。当然,如何进行技术选型,还要依赖具体的业务需求,不可片面理解,断章取义。
下图为两种方式的数据流向,具体区别详见后文描述。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 WebSocket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。创建WebSocket对象:
var Socket = new WebSocket(url, [protocol] );
url:指定连接的URL;
protocol:可选项,指定可接受的子协议;
2.WebSocket
前提是我们已经建立了Socket对象,才会用下面的具体实现:
- WebSocket 属性
- WebSocket 事件
- WebSocket 方法
3.实例分析
- 客户端的HTML和JS
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("您的浏览器支持 WebSocket!");
// 打开一个 web socket
var ws = new WebSocket("ws://localhost:9998/echo");
ws.onopen = function()
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("发送数据");
alert("数据发送中...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert("数据已接收...");
};
ws.onclose = function()
{
// 关闭 websocket
alert("连接已关闭...");
};
}
else
{
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">运行 WebSocket</a>
</div>
</body>
</html>
- 实际项目中的实现方式
最近在实现一个组态化软件与前端的数据传输,也就是在组态软件中嵌入H5的方式,需要实时传输数据,选用的就是WebSocket协议。以下简称为前端、后台:
后台的服务端:需要建立httpserver,进行http连接,连接的参数设置为WebSocket,不同组态软件函数语法略有不同;
前端的JS:首先需要实例化WebSocket对象,
var ws = new WebSocket("URL");
调用函数,向后台发送数据:
ws.onopen = function(){
console.log('已创建连接');
catch_time(); // 获取时间
ws.send(data); // data为传输数据
};
获取后台的数据:
ws.onmessage = function(r){
var o = JSON.parse(r.data);
vm.$data.items = o.items; // vm为Vue对象
dosomthing(); // 具体函数体
}
-
需要注意:
虽然WebSocket协议只需要一次握手就可建立长连接,但是,类似上述应用场景,如果通过浏览器访问H5页面,每次刷新都会形成一次握手操作,那么此时在后台就会形成一个idx,这是打开TCP/IP连接时的内部文件描述符,用以寻址WebSocket;如果前后台的idx不同,数据传输就不会成立,前端无法接收后台数据,注意处理一下idx的问题。可以将每次生成的idx存入数值,每次建立连接时,只取此数组的最新元素即可。