webSocket(与http请求区别、请求和返回示例、替代方法:ajax轮询、long poll、Flash、NodeJS实现WebSocket通信代码、原理、WebSocket构造函数详解)
简介WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。替代方法Ajax 轮询现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出
目录
简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
在http1.1的keep-alive中,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是一个request只能有一个response。而且这个response也是被动的,不能主动发起。
而WebSocket允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
优点
websocket具有以下几个方面的优势:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
请求示例
下面为webSocket的一个请求头信息。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
1. Upgrade: websocket、Connection: Upgrade是告诉服务器要升级为webSocket协议而不是http协议。
2.Sec-WebSocket-Key 是一个Base64 encode的值,这个是浏览器随机生成的,告诉服务器唯一的key值。
3.Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。
4.Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本),在最初的时候,Websocket协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的。
请求成功返回示例
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
1.Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。
2.Sec-WebSocket-Protocol 则是表示最终使用的协议。
替代方法
ajax轮询需要服务器有很快的处理速度和资源。long poll 需要有很高的并发,也就是说同时接待客户的能力。Flash兼容性很差。
Ajax 轮询
浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。现在很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
long poll
采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。
WebSocket 协议能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
Flash
AdobeFlash通过自己的Socket实现完成数据交换,再利用Flash暴露出相应的接口给JavaScript调用,从而达到实时传输目的。此方式比轮询要高效,且因为Flash安装率高,应用场景广泛。然而,移动互联网终端上Flash的支持并不好:IOS系统中无法支持Flash,Android虽然支持Flash但实际的使用效果差强人意,且对移动设备的硬件配置要求较高。2012年Adobe官方宣布不再支持Android4.1+系统,宣告了Flash在移动终端上的死亡。
NodeJS实现webSocket(ws模块)
ws模块是第三方模块,可以用于前端和后端。net模块是nodejs内置模块,用于后端。socket.io也是第三方模块用于兼容非html5的浏览器。
首先通过命令行npm install -s ws安装ws模块
服务端代码
通过node 当前文件名执行。
//导入ws模块
const WebSocket = require('ws');
//获取服务端类
const WebSocketServer =WebSocket.Server
//创建服务端实例
const Server = new WebSocketServer({
port:9527
})
//监听服务端连接事件
Server.on("connection",client =>{
console.log('连接成功')
//监听客户端断开连接事件
client.on('close',()=>{
console.log("连接断开")
})
//监听客户端错误事件
client.on('erro',err=>{
console.log(err)
})
//监听客户端发送的消息
client.on('message',data=>{
console.log('二进制流数据:',data)
//二进制流数据通过toString方法转换为字符串
console.log(data.toString())
//消息转发器它客户端,Server.clients为所有的client的数组
Server.clients.forEach(otherClient=>{
if(client !=otherClient){
otherClient.send(data.toString())
}
})
})
//向客户端发送数据
client.send('你好,客户端~')
})
客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var url = 'ws://127.0.0.1:9527'
//创建WebSocket客户端对象
var ws = new WebSocket(url)
//连接事件
ws.onopen = function () {
console.log('连接事件')
ws.send('你好,我是本地客户端')
}
//关闭连接事件
ws.onclose = function () {
console.log('关闭连接事件')
}
//连接错误事件
ws.onerror = function (err) {
console.log(err)
}
//接收消息事件
ws.onmessage = function (event) {
console.log(event)
//event.data为服务器发送的数据
console.log(event.data)
}
</script>
</body>
</html>
在线网页客户端
在线websocket测试-online tool-postjson
运行结果
先打开服务端,在打开本地网页客户端,在打开在线网页客户端,在在线网页客户端中发送我是在线网站,结果如下图:
服务端运行结果
在线网页客户端运行结果
本地网页客户端运行结果
原理
通信原理
nodejs通过ws模块中的Server构造函数创建服务端,打开如下9527端口监听,当有客户端1连接时,便会在服务端中创建一个client1对象,之后通过client1对象和客户端1进行数据传输,当客户端2连接时便会创建client2,以此类推。
消息转发原理
例如客户端1发送消息到服务端,服务端通过Server.clients拿到所有的client对象,并判断和当前的cliet1对象是否相同,如果不同就把服务端接收到的数据用client转发客户端。
客户端WebSocket构造函数详解
net
nodejs内置的websocket模块。
SocketIO
WebSocket是HTML5最新提出的规范,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验,SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket是SocketIO的一个子集。
实例
服务端代码
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
io.on('connection', function (socket) {//客户端连接事件
socket.on('receive', (msg) => {//监听自定义receive事件,客户端可以通过emit触发,msg为客户端触发时传的数据。
socket.broadcast.emit('message', msg);//向所有连接的客户端处罚message事件,用于广播消息。
})
});
server.listen(8082, '127.0.0.1');
客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>socket.io</title>
<script src="socket.io.js" charset="utf-8"></script>
</head>
<body>
<h1>gp 交流区</h1>
<div id="content" name="name" style="overflow-y: scroll; width: 400px; height: 300px; border: solid 1px #000"></div>
<br />
<div>
<input type="text" id="msg" style="width: 200px;">
</div>
<button id="submit">提交</button>
<script>
var socket = io.connect('http://127.0.0.1:8082');
const content = document.getElementById('content')
document.querySelector('#submit')
.addEventListener('click', function () {
var msg2 = msg.value
socket.emit('receive', msg2) // 触发receive事件像服务端传递数据,服务端通过监听相同事件名,获取数据。
msg.value = ''
content.innerHTML += msg2 + '<br/>'
}, false)
socket.on('message', function(msg){//监听服务端触发的message事件
content.innerHTML += msg + '<br/>'
})
</script>
</body>
</html>
官网
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)