本教程从webSocket是什么及特点、webSocket的应用、webSocket原理、webSocket案例实现、注意点五个部分来讲解webSocket的入门到实际使用
一、webSocket是什么及特点?
1、webSocket是一种在单个TCP连接上进行全双工通信协议,即数据可以同时双向传输;
2、WebSocket是一种持久化网络通信协议,一次握手即可建立长连接(握手使用HTTP协议,所以不容易被屏蔽,能通过各种HTTP代理服务器),与HTTP协议不同,HTTP需要三次握手,并且无状态,即每次通信请求都是唯一的,通过session、cookie配对等方式来认识每次请求;
3、WebSocket可以实现服务器主动推送数据给客户端,即可以做到服务器端与客户端的实时通信,与HTTP协议不同,HTTP需要每次客户端发给请求,服务器端才会给出响应,不过基于HTTP也可实现实时通信技术,例如:轮询、长轮询、流化技术(不过有弊端);
4、可以发送文本、二进制数据,数据格式比较轻量,性能开销小;
5、不受同源策略限制,因此不必理会跨域问题;
6、与HTTP协议一样有着良好的兼容性,默认端口是80和443。
二、WebSocket的应用
webSocket的最显著的应用特点就是实时,像常见的微信、QQ聊天室,股票基金走势等等,这些注重于实时数据的接收与发送都可以使用webSocket。
三、WebSocket原理
![](https://img-blog.csdnimg.cn/af0289dfe8ef4347b35c25ca605a9ba4.png)
在发送HTTP请求的请求头中:
1. Connection和Upgrade字段会告诉服务器,客户端要对协议升级,升级成为WenSocket协议。
2. Sec-WebSocket-Key是一个Base64编码值,是由浏览器随机生成。
3. Sec-WebSocket-Version表示客户端所使用的协议版本。
在响应头中:
1. Connection字段表示协议已经升级。
2. Sec-WebSocket-Accept表明服务器接受了客户端的请求。
3. Upgrade字段表示协议升级成为了WenSocket协议。
四、webSocket案例实现
1、单一客户端与服务端之间的实时通信(实现在客户端发送给服务端数据后,服务端接收响应数据后,无需客户端再次发起请求,直接将数据发送给客户端)
下面的案例只是将客户端接收到服务器端的信息直接输出到了控制台,并没有做精美的页面来展示服务端消息。
使用node创建本地服务器
服务器端代码:
var Websocket = require('websocket').server
var http = require('http')
//监听8080端口,服务器启动时控制台输出,因为websocket第一次请求需要走HTTP协议,所以创建HTTP服务器
var httpServer = http.createServer().listen(8080, function(){
console.log('http://127.0.0.1:8080');
})
//创建Websocket实例
var wsServer = new Websocket({
httpServer: httpServer,
autoAcceptConnections: false
})
//监听请求
wsServer.on('request', function(request){
// request.accept()是拿到wsServer链接实例
var connection = request.accept()
// 监听到达服务器的消息事件
connection.on('message', function(msg){
//当有数据到达服务器即使用send()API向客户端发出数据
connection.send(msg)
})
})
客户端代码:
<!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>
<input type="text" id="text">
<input type="button" value="发送" onclick="send()" ></input>
<script>
//与服务器建立连接
var websocket = new WebSocket('ws://127.0.0.1:8080')
console.log(websocket.readyState);
// readyState是当前websocket实例状态:
//0链接还没有建立(正在建立连接)
// 1链接建立成功
// 2链接正在关闭
// 3链接已经关闭
//websocket.onopen被触发的时候事件
websocket.onopen = function(){
console.log(websocket.readyState);
}
//点击发送给服务端发出数据,也是使用send()API发出数据
function send(){
var text = document.getElementById('text').value
websocket.send(text)
}
// 监听服务器推送事件(当服务器有消息发送过来即在控制台输出数据,在这里可以直观的看见,
//客户端没有给服务器端发出请求,但当服务器端接收到消息后就主动给客户端发出了数据)
websocket.onmessage = function(back){
console.log(back.data);
console.log(back);
}
</script>
</body>
</html>
2、多个客户端与服务端之间的实时通信(实现在一个客户端发送给服务端数据后,服务端接收响应数据后,无需客户端再次发起请求,直接将数据发送给当前所有客户端,类似群聊功能)
在实现聊天室的案例里,只是将每一个websocket链接实例放进数组,再使用for循环向对应的客户端发送数据.看到这里我们可以小小的猜测一下为什么聊天软件的群聊为什么都有人数限制了?
服务器端代码:
var Websocket = require('websocket').server
var http = require('http')
var httpServer = http.createServer().listen(8080, function(){
console.log('http://127.0.0.1:8080');
})
var wsServer = new Websocket({
httpServer: httpServer,
autoAcceptConnections: false
})
var connectionArr = []
// 服务端向多个客户端群发消息
wsServer.on('request', function(request){
// request.accept()是拿到wsServer链接实例
var connection = request.accept()
//将所有wsServer链接实例放进数组,即形成链接池
connectionArr.push(connection)
// 监听到达服务器的消息事件
connection.on('message', function(msg){
//使用for循环实现链接池中的每一个链接向对应客户端发出消息
for(var i = 0;i<connectionArr.length;i++){
connectionArr[i].send(msg.utf8Data)
}
})
})
客户端代码与第一个案例无异:
<!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>
<input type="text" id="text">
<input type="button" value="发送" onclick="send()" ></input>
<script>
var websocket = new WebSocket('ws://127.0.0.1:8080')
websocket.onopen = function(){
console.log(websocket.readyState);
}
function send(){
var text = document.getElementById('text').value
websocket.send(text)
}
// 监听服务器推送事件
websocket.onmessage = function(back){
console.log(back.data);
console.log(back);
}
</script>
</body>
</html>