websocket序言
WebSocket啊,简单来说,就像是一条永远不打烊的"高速通道",让服务器和客户端能够随时随地"煲电话粥"。有了它,服务器再也不用等着客户端来敲门了,可以主动发起聊天,告诉客户端:"嘿,我这里有新消息要告诉你!"而客户端呢,也可以随时回应:"收到啦,谢谢!"
这条"高速通道"不仅速度快,还特别节省流量。想想看,传统的Ajax/HTTP请求每次都要"敲门""问好""报身份",多费劲啊!而WebSocket呢,一旦建立了连接,就像打开了"免提",大家都可以畅所欲言,不用每次都重复那些客套话了。
那么我们应该如何打开websocket的第一扇门呢?
从上篇文章 WebSocket: 实时通信的魔法快递,让你的网络生活飞跃升级!
已经提及
WebSocket 复用了 HTTP 的握手通道,要建立 WebSocket 通信,需要在连接发起方的 HTTP 请求报文中通过 Upgrade 字段告知服务器通信协议升级到 Websocket,然后通过 Sec-WebSocket-* 扩展字段提供 WebSocket 的协议、版本、键值等信息 , 而服务器会返回 101 Switching Protocols
响应表示协议升级成功
简单的,可以用下图理解下流程:
WebSocket 真是个聪明的家伙!它巧妙地借用了 HTTP 协议来完成初次握手,然后借助神奇的 Upgrade 字段,成功地把HTTP协议升级成了 WebSocket 协议,建立起一个持久的长连接。一旦这个连接建立起来,客户端和服务端就能随时随地通过 WebSocket 数据帧进行愉快的双向沟通啦!这意味着,不管是客户端还是服务端,都可以随时给对方发送信息,不再像HTTP协议那样,非得等客户端先开口,服务端才能回应。这种灵活的通信方式,完美解决了Web页面实时更新资源的大难题.
实战Demo
在本篇分享中,我将在服务端基于 Node 实现简单的 WebSocket 服务器,然后在客户端基于 JavaScript 实现 WebSocket 客户端,通过这个简单的实现, 加深大家对 WebSocket 通信过程的理解。希望能帮到大家谢谢,给点个小赞。
WebSocket 服务器
代码:
创建一个名为node.js
的文件,并输入以下代码:
JS
const WebSocket = require('ws')
// 创建WebSocket服务器监听端口3000
const wss = new WebSocket.Server({ port: 3000 })
wss.on('connection', function connection(ws) {
// 当客户端连接时,打印连接
console.log('connected')
// 当接收到客户端消息时,打印消息内容并将其发送回客户端
ws.on('message', function incoming(message) {
console.log('received: %s', message)
ws.send('echo: ' + message)
})
// 当连接关闭时,打印信息
ws.on('close', function close() {
console.log('disconnected')
})
ws.send('Welcome to the WebSocket server!')
// 发送欢迎消息给客户端
// setInterval(function () {
// ws.send('Welcome to the WebSocket server!')
// }, 3000)
})
console.log('WebSocket server is running on ws://localhost:3000')
解读:
- 引入
ws
库:
javascript
const WebSocket = require('ws')
这行代码导入了 ws
库,该库为 Node.js 提供了 WebSocket 服务器的实现。
- 创建 WebSocket 服务器:
javascript
const wss = new WebSocket.Server({ port: 3000 })
这行代码创建了一个新的 WebSocket 服务器实例,并监听 3000 端口。当客户端连接到此端口时,WebSocket 服务器将与其建立连接。
- 监听
connection
事件:
javascript
wss.on('connection', function connection(ws) {
// ...
})
每当有新的 WebSocket 客户端连接到服务器时,connection
事件都会被触发。该事件的回调函数接收一个参数 ws
,它是一个表示新连接的 WebSocket 实例。
- 处理连接:
javascript
console.log('connected')
当客户端连接到服务器时,会在控制台上打印 connected
。
- 监听
message
事件:
javascript
ws.on('message', function incoming(message) {
console.log('received: %s', message)
ws.send('echo: ' + message)
})
当服务器从连接的客户端接收到消息时,message
事件会被触发。在回调函数中,首先打印接收到的消息内容,然后向客户端发送一个带有 echo:
前缀的响应消息。
- 监听
close
事件:
javascript
ws.on('close', function close() {
console.log('disconnected')
})
当 WebSocket 连接关闭时,close
事件会被触发。在回调函数中,打印 disconnected
表示连接已断开。
- 发送欢迎消息:
javascript
ws.send('Welcome to the WebSocket server!')
当客户端连接后,服务器会立即发送一条欢迎消息给客户端。
WebSocket 客户端
代码:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>梦幻星辰吧 Client</title>
</head>
<body>
<script>
window.onload = function () {
var nick = prompt("Enter your nickname");
var input = document.getElementById("input");
input.focus();
// 初始化客户端套接字并建立连接
var socket = new WebSocket("ws://localhost:3000");
// 连接建立时触发
socket.onopen = function (event) {
console.log("Connection open ...");
}
// 接收到服务端推送时执行
socket.onmessage = function (event) {
var msg = event.data;
var node = document.createTextNode(msg);
var div = document.createElement("div");
div.appendChild(node);
document.body.insertBefore(div, input);
input.scrollIntoView();
};
// 连接关闭时触发
socket.onclose = function (event) {
console.log("Connection closed ...");
}
input.onchange = function () {
var msg = nick + ": " + input.value;
// 将输入框变更信息通过 send 方法发送到服务器
socket.send(msg);
input.value = "";
};
}
</script>
<input id="input" style="width: 100%;">
</body>
</html>
解读:
当页面加载完成时,会执行window.onload
中的函数。
- 获取昵称:
javascript
var nick = prompt("Enter your nickname");
通过prompt
函数,页面会弹出一个提示框,要求用户输入其昵称,并将其赋值给nick
变量。
从DOM中获取ID为"input"的元素,并设置其为当前焦点,这样用户可以直接开始输入。
- 初始化WebSocket连接:
javascript
var socket = new WebSocket("ws://localhost:3000");
创建一个新的WebSocket对象,并尝试与在本地主机上运行的、端口号为3000的WebSocket服务器建立连接。
- 处理连接打开事件:
javascript
socket.onopen = function (event) {
console.log("Connection open ...");
};
当WebSocket连接成功打开时,此函数会被触发,并在控制台输出"Connection open ..."。
- 处理接收到的消息:
javascript
socket.onmessage = function (event) {
var msg = event.data;
var node = document.createTextNode(msg);
var div = document.createElement("div");
div.appendChild(node);
document.body.insertBefore(div, input);
input.scrollIntoView();
};
当从服务器接收到消息时,此函数会被触发。消息内容存储在event.data
中。然后,代码会创建一个新的div
元素,将消息内容作为文本节点添加到该div
中,并将该div
插入到输入框前面。最后,通过scrollIntoView()
方法确保输入框在视口中可见。
- 处理连接关闭事件:
javascript
socket.onclose = function (event) {
console.log("Connection closed ...");
};
当WebSocket连接关闭时,此函数会被触发,并在控制台输出"Connection closed ..."。
- 处理输入框内容变更:
javascript
input.onchange = function () {
var msg = nick + ": " + input.value;
socket.send(msg);
input.value = "";
};
当输入框的内容发生变化时(例如,用户输入文本并按下Enter键),此函数会被触发。它创建一个消息字符串,其中包含用户昵称和输入框的值,并通过socket.send()
方法发送到服务器。然后,清空输入框的值,以便用户可以继续输入新的消息。
运行结果:
用serve或其他工具启动web服务,访问客户端页面,
服务端这个时候接收到客户端的链接请求,并打印如下信息:
输入之后点击确定,JavaScript 代码会继续往下执行,让输入框获取焦点,然后初始化 WebSocket 客户端并连接到服务器,这个时候通过开发者工具可以看到 Console 标签页已经输出了连接已建立日志
这个时候我们在客户端输入,client,WebSocket!
服务端通过该方法,
js
// 当接收到客户端消息时,打印消息内容并将其发送回客户端
ws.on('message', function incoming(message) {
console.log('received: %s', message)
ws.send('echo: ' + message)
})
接收到信息,并打印:
总结:
哈哈,你可能会觉得!虽然这段代码里看起来像是客户端主动找服务器要消息,但WebSocket的真正魅力在于,一旦它们"握手"成功,服务器就能变成个"消息小达人",随时随地给客户端推送最新动态。就像你在网上订了个外卖,不用一直刷新页面看厨师做好了没,厨师做好后会直接通知你一样。
在实际项目中,WebSocket 就像一个永不休息的快递员,不管白天黑夜,只要有新的"包裹"(消息),它就会立刻送到你的手上。这样,你就不再需要时不时地去"邮局"(服务器)查询了,轻松又方便!
所以,别小看这简单的几行代码,它们可是实现实时通信的"神器"哦!下次当你看到那些实时更新的信息、聊天界面的消息闪烁时,不妨想想背后的WebSocket"小达人"们,它们正在默默地为你传递着世界的最新动态呢!