前言
在面试考题中,如果面试官问关于http协议相关的知识或者直接让你实现一个类似QQ消息的发送,这时候就可以讲到websocket相关的知识了。
那就让我们先来了解一下基础协议相关的技术,再实现会话功能。
1.基础协议与技术
1.1 TCP/IP 协议
TCP/IP 是互联网的基础协议,负责数据的传输。它通过三次握手建立连接,并通过四次挥手断开连接。这种机制确保了数据传输的可靠性。
1.2 HTTP 协议与 Socket
HTTP 协议是应用层协议,通常用于浏览器与服务器之间的通信。它是无状态的,即每次请求都是独立的,服务器不会记住之前的请求。而 Socket 是一种更底层的通信机制,可以实现长连接、消息推送和广播等功能。
1.3 B/S 架构
B/S(Browser/Server)架构是常见的Web应用架构,用户通过浏览器与服务器进行交互。在这种架构下,即时通讯功能通常需要借助 WebSocket 协议来实现。
2. HTTP 与 WebSocket 的区别
先上图表:
2.1 状态性
- HTTP 是无状态的,每次请求都是独立的,服务器不会记住客户端的状态。
- WebSocket 是有状态的:服务器会为每个连接保持一个持久的双向通信通道。开发者可以自定义唯一的标识符(如 Socket ID)来管理和区分不同的客户端连接.
2.2 通信方式
- HTTP 是单向的,客户端发起请求,服务器返回响应,服务器不能主动向客户端发送消息。
- WebSocket 是双向的,客户端和服务器可以随时向对方发送消息。
2.3 通信模式
- HTTP 是基于请求-响应的,客户端发起请求后,服务器返回响应,通信结束。
- WebSocket 是基于事件的,客户端和服务器可以通过事件(如
onmessage
)来实时接收消息。
3. WebSocket 服务搭建流程
3.1 基于 HTTP 服务访问聊天页面
首先,我们需要基于 HTTP 服务访问聊天页面。用户通过浏览器访问 http://localhost:3001/
,服务器返回一个包含 WebSocket 连接的 HTML 页面。(在这里使用了koa框架和koa-websocket来实现)
js
const Koa = require('koa');
const websocket = require('koa-websocket');
const app = websocket(new Koa()); // 开启一个应用实例
const clients = new Set();
app.use(async (ctx, next) => {
ctx.body = `
<html>
<body>
<div id="messages" style="height: 300px; overflow-y: scroll;"></div>
<input type="text" id="messageInput" />
<button onclick="sendMessage()">发送</button>
<script>
const ws = new WebSocket('ws://localhost:3001');
ws.onmessage = function(event) {
const messages = document.getElementById('messages');
messages.innerHTML += "<div>" + event.data + '<br/>';
}
function sendMessage() {
const msg = document.getElementById('messageInput').value.trim();
ws.send(msg);
}
</script>
</body>
</html>
`;
});
3.2 WebSocket 连接建立
当用户访问页面后,浏览器会通过 WebSocket 协议向服务器发起连接请求。服务器返回状态码 101 Switching Protocols
,表示协议切换成功,后续通信将使用 WebSocket 协议。
js
app.ws.use(async (ctx, next) => {
clients.add(ctx.websocket);
ctx.websocket.on('message', (message) => {
for (const client of clients) {
client.send(message.toString()); // 服务器广播给所有的用户
}
});
ctx.websocket.on('close', () => {
clients.delete(ctx.websocket);
});
});
// http 伺服
app.listen(3001,()=>{
console.log('server is running at port 3001')
})
3.3 消息的发送与接收
在 WebSocket 连接建立后,客户端和服务器可以通过 send
方法发送消息,并通过 onmessage
事件接收消息。服务器可以将接收到的消息广播给所有连接的客户端,实现群聊功能。
3.4 实现效果:
打开两个伺服端口,模拟两个用户之间进行对话,在第一个用户中发送消息,第二个接收,第二个用户发送消息,第一个用户也成功接收
4.执行流程:
当你打开页面并发送一个消息时:
-
加载页面:
- 用户访问
ws://localhost:3001
(或通过其他方式触发Koa应用),Koa应用返回一段HTML代码作为响应。 - 浏览器解析这段HTML代码,并渲染出一个包含输入框和按钮的简单界面。
- 用户访问
-
建立WebSocket连接:
- 页面加载完成后,JavaScript代码立即创建一个新的WebSocket实例
ws = new WebSocket('ws://localhost:3001')
,尝试与服务器建立WebSocket连接。 - 服务器端通过
app.ws.use()
注册的中间件监听到新的WebSocket连接请求,并将该连接添加到clients
集合中,这标志着WebSocket连接成功建立。
- 页面加载完成后,JavaScript代码立即创建一个新的WebSocket实例
-
用户输入消息并点击发送按钮:
- 当用户在输入框内输入文本并点击"发送"按钮后,
sendMessage()
函数被调用。 - 函数获取输入框内的值,通过WebSocket对象的
send()
方法将消息发送至服务器。
- 当用户在输入框内输入文本并点击"发送"按钮后,
-
服务器接收并广播消息:
- 服务器端通过监听WebSocket连接的
message
事件来接收客户端发来的消息。 - 收到消息后,服务器遍历所有已连接的客户端(存储于
clients
集合中),并通过每个客户端的send()
方法将消息转发给它们,实现消息的广播。
- 服务器端通过监听WebSocket连接的
-
客户端显示接收到的消息:
- 客户端通过监听WebSocket对象的
onmessage
事件来处理从服务器接收到的消息。 - 每当收到新消息时,更新页面上的
<div id="messages">
元素内容,将新消息追加到已有消息列表的末尾,从而实现实时显示消息的功能。
- 客户端通过监听WebSocket对象的
END
如果觉得哥们的文章对你有帮助,也请给我点个赞吧!