一、HTTP是无状态协议
特点:
1、浏览器发送请求时,浏览器和服务器会建立一个连接。完成请求和响应。在http1.0之前,每次请求响应完毕后,会立即断开连接。在http1.1之后,当前网页的所有请求响应完毕后,才断开连接。
2、这样就意味着,服务器并不清楚,某次连接和以前的哪个连接来自于同一个客户端。换句话说。服务器没法区分不同的客户端。为了解决这个问题。在web开发中提供了session(服务器端的技术)和cookie(浏览器端)的配合。完成识别不同的客户端。
3、服务器如何识别不同的客户端(这是原理,不需要程序员干预)。
当前浏览器端首次发生请求时,服务端会产生一个sessionId(编号)把sessionId保存在服务器端,同时,把sessionId发给客户端,客户端会在cookie里保存。
当浏览器二次方式请求时,会携带首次请求的sessionId给服务器端。服务器端根据sessionId来区分不同的客户端。
由于http是无状态的协议(请求响应完毕后,会断开连接)既就是短连接。再加之http协议是被动的(浏览器端部不发生请求,服务器端不响应)。如果要做网页的聊天/即时了解。就需要使用到webscoket技术。
二、webSocket
1、socket
socket应用
Web领域的实时推送技术,也被称作Realtime技术。这种技术要达到的目的是让用户不需要刷新浏览器就可以获得实时更新。它有着广泛的应用场景,比如WebIM( 网页聊天 )、在线客服系统、评论系统等。 而曾经的HTTP协议,是无状态的协议,一次交互完成后,连接就断开了。所以,服务器端和客户端就没有连接(也就是说,服务器端并不能拿到聊天的客户端)。只有客户端发送请求,服务器才知道那些客户端连接了。所以http是被动的协议(客户端不请求,服务器端不响应,显然不能满足需求)。HTML5提供的websocket协议可以主动推送信息。
socket介绍
socket:插座;套接字 网络上的两个程序通过一个双向(全双工)的通信连接实现数据的交换,这个连接的一端称为一个socket。就像用座机打电话,给两个座机都插上电话线,就可以打电话,即语音信息的交流。
socket的通讯流程
服务器端(电话的一端,接听电话者):
1、创建socket,表示有了一个电话
2、绑定socket和端口号,相当于,电话对应了一个电话号码
3、监听端口号,相当于,把电话插上电话线,可以随时等待有人拨通电话
4、接收客户端的连接请求,相当于有人打来了电话
5、从socket中读取字符,相当于,接起电话,有语音信息传输过来了
6、关闭socket,相当于通话完成后,挂掉电话
客户端:
1、 创建socket,表示有了一个电话(当然也默认绑定了端口号)
2、连接指定的计算机端口(服务器的地址和端口),相当于拨打电话
3、向socket中写入信息,相当于给对方说话
4、关闭socket,相当于通话完成后,挂掉电话
2、webSocket
WebSocket是HTML5新增加的原生的对象,是一个通信的协议(ws协议)。是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。在WebSocket API中,浏览器和服务器只需要做一个握手(handshaking)的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
单工: 只能单向, 传呼机 半双工:双向,但是同时,只能单向,对讲机 全双工:双向,可以同时传输信息,电话
对比webSocket协议和http协议:
HTTP协议是不支持持久连接的(长连接)
Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。
webSocket对象介绍
属性
属性 | 描述 |
---|---|
readyState | 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。 |
bufferedAmount | 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数 |
事件
事件 | 事件处理程序 | 描述 |
---|---|---|
connection | 连接事件 | |
open | Socket.onopen | 连接建立时触发 |
message | Socket.onmessage | 客户端接收服务端数据时触发 |
error | Socket.onerror | 通信发生错误时触发 |
close | Socket.onclose | 连接关闭时触发 |
方法
方法 | 描述 |
---|---|
send() | 使用连接发送数据 |
close() | 关闭连接,同时会触发另外一端的close事件 |
使用步骤:
一、服务器端
1、安装ws模块(webSocket)
npm i ws --save
ws:是nodejs的一个WebSocket库,可以用来创建服务。
客户端send函数触发 服务器官方事件message。
2、服务器端代码:
var WebSocketServer = require('ws').Server;
//创建webSocket的服务器对象,同时需要设定端口号。
var wss = new WebSocketServer({ port: 9000 });
let clients = []; //记录客户端对象
let i =0; //记录客户端 序号
//绑定事件connection,此事件是当有客户端连接时,触发
wss.on('connection', function (ws) { //ws就是连接的客户端对象ws.name = ++i; clients.push(ws) //把客户端对象保存起来//给客户端对象绑定事件message,当客户端发送信息时,触发该事件ws.on('message', function (message) { //给客户端对象绑定message事件,有信息发过来了。broadcast(message, ws) //把客户端发送来的信息,广播给其它客户端。 })ws.on('close', function () { //给客户端对象绑定close事件,客户端关闭了console.log('离开');})})//广播信息
function broadcast(msg, ws) {//broadcast是把信息发布(广播)给其它客户端for (var key in clients) { //clients: 记录着所有的客户端对象clients[key].send(ws.name + '说: ' + msg)}
}
3、客户端代码
//js代码:WsClient.js
//new WebSocket(),就触发了服务器端的connection事件
var ws = new WebSocket('ws://127.0.0.1:9000/')
//当连接上服务器端,即打开连接后,触发
ws.onopen = function () {ws.send('大家好')
}
//当接收到(服务器端的)信息后,触发
ws.onmessage = function (event) {var chatroot = document.getElementById('chatroom');chatroom.innerHTML += '<br/>' + event.data
}
//当服务器端关闭时,触发
ws.onclose = function () {console.log('Closed')
}
//当出错时,触发
ws.onerror = function (err) {alert('Error:' + err)
}
//html代码
<h1>WebSocket</h1><div id="chatroom" style="width:400px;height:300px;overflow:auto;border:1px solid blue"></div><input type="text" name="sayinput" id="sayinput" value=""><input type="button" name="send" id="sendbutton" value="发送"><script src="WsClient.js"></script>
<script type="text/javascript">function send() {ws.send(sayinput.value);sayinput.value = '';}
document.onkeyup = function (event) {if (event.keycode == 13) {send();}}sendbutton.onclick = function () {send();}</script>
3、socket.io
介绍:
如果浏览器不支持HTML5,即没法直接使用websocket。我们还需要使用socket.io来考虑兼容性。即,如果支持HTML5,就用websocket,如果不支持HTML5就使用socket.io。Socket.io使用检测功能来判断是否建立WebSocket连接。Socket.IO还提供了一个NodeJS API
思路:
服务器和客户端用触发自定义事件的方式传递数据
代码:
1、 使用node 的express和socket.io
2、 安装express 3、 安装socket.io
npm i express socket.io
前端代码需要引入“socket.io.js”
服务器端:
const server = require('http').createServer();
const io = require("socket.io")(server, {allowEIO3: true,// 解决跨域问题cors: {origin: "*", // from the screenshot you providedmethods: ["GET", "POST"]}
});
server.listen(9009,()=>{console.log("启动成功!");
});
io.on('connection', () => { console.log("")
});
//保存所有的客户端
var clients = {};
io.sockets.on('connection', function (socket) {console.log("connection被触发了");//有客户端连接,发送消息 (f 是自定义事件)socket.on('f', function (sayer, fn) {//如果没有保存改客户端,那么就保存该客户端if (!clients[sayer]) {clients[sayer] = this;}console.log(clients);fn();});socket.on('message', function (data) {console.log("message被触发了");broadcast(data);});function broadcast(data){for(let key in clients){//给客户端发送消息,使用事件,emit触发事件 news clients[key].emit('news',data);}}});
客户端:
<!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><div id="chatroom" style="width:400px;height:300px;overflow:auto;border:1px solid blue"></div><input type="text" id="sayer" >说:<input type="text" id="sayConent" ><input type="button" id="sendbutton" value="发送">
</body>
</html>
<script src="./js/socket.io.js"></script>
<script>
sayer.value = "游客"+Date.parse((new Date()).toUTCString());
// 创建对象,并连接服务器端(触发服务器端的connection事件)
const socket = io.connect("http://127.0.0.1:9009");
// 连接事件
socket.on("connect",function(){console.log("connect");// 连接建立起来后,打个招呼socket.emit('f',sayer.value, function () {socket.send(sayer.value+"说:hello !"); //send函数触发的是服务器端message事件});
});
socket.on("news",function(data){console.log("news被触发了");chatroom.innerHTML += data+"<br/>";
})
sendbutton.onclick = function(){socket.send(sayer.value+"说:"+sayConent.value); sayConent.value="";
}
</script>
如果想看视频(websocket和uni-app里使用websocket),请使用如下链接:
01webscoket.mp4 等文件 https://www.aliyundrive.com/s/D7jLbQSvCGk