模式切换
WebSocket 网络编程
WebSocket 是一种在客户端和服务器之间建立全双工通信通道的协议。与传统的 HTTP 请求/响应机制不同,WebSocket 允许在客户端和服务器之间进行持续的、实时的数据交换,广泛应用于在线聊天、游戏、实时通知等场景。
WebSocket 网络编程的基本实现
WebSocket 服务端的实现
在 Node.js 中,我们可以使用 ws
模块来实现 WebSocket 服务端。以下是一个简单的 WebSocket 服务端实现:
首先,安装 ws
模块:
bash
npm install ws
然后,创建一个 WebSocket 服务器:
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('A new client connected');
// 监听客户端消息
ws.on('message', (message) => {
console.log(`Received message: ${message}`);
});
// 向客户端发送消息
ws.send('Hello from the server!');
});
在这个服务端代码中,我们创建了一个 WebSocket 服务器,监听 8080
端口,并处理来自客户端的连接。当客户端发送消息时,服务端会打印消息并响应一个简单的文本消息。
WebSocket 客户端的实现
WebSocket 客户端可以在浏览器或 Node.js 中实现。下面是一个在浏览器中实现 WebSocket 客户端的例子:
javascript
const socket = new WebSocket('ws://localhost:8080');
// 连接成功时的回调
socket.onopen = () => {
console.log('Connected to the server');
socket.send('Hello, server!');
};
// 接收到消息时的回调
socket.onmessage = (event) => {
console.log(`Received: ${event.data}`);
};
// 连接关闭时的回调
socket.onclose = () => {
console.log('Connection closed');
};
在客户端代码中,我们通过 new WebSocket(url)
创建了一个 WebSocket 连接,并定义了事件处理器来处理连接的打开、消息的接收和连接的关闭。
服务端与客户端的通信
WebSocket 允许双向通信。客户端可以向服务端发送消息,服务端也可以主动向客户端发送消息。以下是一个完整的例子,展示了服务端与客户端之间的双向通信:
服务端代码(Node.js):
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('A new client connected');
// 向客户端发送欢迎消息
ws.send('Welcome to the WebSocket server!');
// 监听客户端消息
ws.on('message', (message) => {
console.log(`Received: ${message}`);
ws.send(`Server received: ${message}`);
});
});
客户端代码(浏览器):
javascript
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = () => {
console.log('Connected to the server');
socket.send('Hello, server!');
};
socket.onmessage = (event) => {
console.log(`Received: ${event.data}`);
};
在这个例子中,客户端向服务端发送消息,并且服务端会回应一个确认信息。
Socket 数据通信类型
WebSocket 提供了不同的通信模式,常见的包括 public
(公开广播)、broadcast
(广播给所有连接的客户端)和 private
(私密通信)。
public 通信类型
Public 通信是指将数据发送给所有连接的客户端,适用于需要全员同步的场景,比如聊天室中的公共消息。
服务端广播给所有客户端:
javascript
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// 向所有客户端广播消息
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
在这个例子中,服务端接收到某个客户端发送的消息后,会将该消息广播给所有连接的客户端,除了发送消息的客户端本身。
broadcast 通信类型
Broadcast 通信是指向所有连接的客户端发送相同的消息,但并不一定是所有客户端都能接收到数据。例如,聊天室中的通知消息可以广播给所有用户。
这与 public 通信非常相似,唯一的区别是可以进行某些过滤或处理,决定哪些客户端应该接收消息。例如,只向某些特定的客户端广播消息。
javascript
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// 仅向部分客户端广播
if (message === 'some_condition') {
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send('Condition met, broadcasting...');
}
});
}
});
});
private 通信类型
Private 通信是指客户端与服务端之间的私密通信,或者是客户端与客户端之间的私密通信。例如,聊天应用中的私信功能就是私密通信。
服务端和特定客户端进行私密通信:
javascript
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// 发送私信给特定的客户端
if (message.startsWith('private:')) {
const targetClient = findClientById(message.split(':')[1]);
if (targetClient) {
targetClient.send('Private message: ' + message);
}
}
});
});
// 模拟查找客户端的方法
function findClientById(id) {
return Array.from(wss.clients).find(client => client.id === id);
}
在这个例子中,客户端可以向服务端发送以 private:
开头的消息,服务端根据消息内容找到特定的客户端,并向该客户端发送私密消息。
客户端分组的实现
在实际应用中,可能需要根据某些规则将客户端分组,并在组内进行通信。客户端分组可以通过 client
的标识符(如 id
)进行管理。常见的分组场景包括聊天室的不同房间或游戏中的不同队伍。
分组管理:
javascript
const groups = {};
wss.on('connection', (ws) => {
// 每个客户端都有一个唯一的 groupId
ws.on('message', (message) => {
const { groupId, msg } = JSON.parse(message);
// 将消息发送给同组内的所有客户端
if (groups[groupId]) {
groups[groupId].forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(msg);
}
});
}
});
// 加入某个分组
ws.on('joinGroup', (groupId) => {
if (!groups[groupId]) {
groups[groupId] = [];
}
groups[groupId].push(ws);
});
// 离开某个分组
ws.on('leaveGroup', (groupId) => {
if (groups[groupId]) {
const index = groups[groupId].indexOf(ws);
if (index !== -1) {
groups[groupId].splice(index, 1);
}
}
});
});
通过这种方式,客户端可以根据 groupId
加入某个分组,分组内的客户端可以互相发送消息。