下面是针对“Nodejs实现WebSocket代码实例”的完整攻略,包含代码示例和详细说明:
什么是WebSocket
WebSocket是HTML5提出的一种新型通信协议,它建立在传输层TCP协议之上,并通过HTTP协议进行握手。WebSocket协议的特点是支持全双工通信、实时性更高、更省带宽、更灵活、能够实现跨域通信等。
Nodejs实现WebSocket的原理
Node.js中实现WebSocket通信需要依赖两个核心模块ws
和http
模块,前者用于WebSocket通信,后者用于提供HTTP请求服务。
WebSocket通信的过程可以简化为以下步骤:
- 客户端发送一个WebSocket请求,请求报文中包含WebSocket key和协议版本信息。
- 服务端收到WebSocket请求,校验WebSocket key并返回HTTP响应报文,包含一个握手响应头Sec-WebSocket-Accept以及协议版本信息。
- 客户端收到握手响应后,判断Sec-WebSocket-Accept是否与自己生成的WebSocket key匹配,如果匹配则认为握手成功,开始进行WebSocket通信。
实现WebSocket通信的关键是进行握手,需要在服务端接收到WebSocket请求后进行握手处理。
握手的过程示例代码如下:
const http = require('http');
const crypto = require('crypto');
const websocket = require('ws');
const server = http.createServer((req, res) => {
//处理WebSocket握手
if (req.headers.connection === 'Upgrade' && req.headers.upgrade === 'websocket') {
const secWebSocketKey = req.headers['sec-websocket-key'];
const secWebSocketAccept = crypto
.createHash('sha1')
.update(secWebSocketKey + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', 'binary')
.digest('base64');
res.writeHead(101, {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Accept': secWebSocketAccept
});
const ws = new websocket.WebSocket({ server: server });
ws.on('connection', function (socket) {
console.log('webSocket server connected');
socket.on('message', function (message) {
console.log('received: %s', message);
});
socket.send('Hello from WebSocket server');
});
} else {
//处理HTTP请求
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}
});
server.listen(8080);
console.log('Server running on port 8080.');
在代码中,我们通过http.createServer
创建了一个HTTP请求服务,当收到WebSocket请求时,会进入到握手处理逻辑中。
首先取出WebSocket key,生成WebSocket Accept,然后通过res.writeHead
设置响应报文头,包括状态码101、Connection和Upgrade字段以及Sec-WebSocket-Accept字段。此外,还需要创建一个websocket对象,该对象监听connection事件,并在连接成功后,处理收到的消息并返回一个问候信息。
Nodejs实现WebSocket的使用示例
在第一个示例中,我们将通过WebSocket连接模拟客户端和服务端之间的聊天,服务端收到客户端发送的消息后,通过WebSocket通道将消息推送给所有已连接的客户端。
服务端代码:
const http = require('http');
const crypto = require('crypto');
const websocket = require('ws');
const server = http.createServer((req, res) => {
//处理WebSocket握手
if (req.headers.connection === 'Upgrade' && req.headers.upgrade === 'websocket') {
const secWebSocketKey = req.headers['sec-websocket-key'];
const secWebSocketAccept = crypto
.createHash('sha1')
.update(secWebSocketKey + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', 'binary')
.digest('base64');
res.writeHead(101, {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Accept': secWebSocketAccept
});
const ws = new websocket.WebSocket({ server: server });
ws.on('connection', function (socket) {
console.log('webSocket server connected');
socket.on('message', function (message) {
console.log('received: %s', message);
ws.clients.forEach(client => {
if (client.readyState === websocket.OPEN) {
client.send(message);
}
});
});
});
} else {
//处理HTTP请求
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}
});
server.listen(8080);
console.log('Server running on port 8080.');
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat Example</title>
<script>
let socket;
function connect() {
socket = new WebSocket('ws://localhost:8080');
socket.onopen = function () {
console.log('WebSocket connection opened.');
}
socket.onmessage = function (e) {
console.log('received: ' + e.data);
const messages = document.getElementById('messages');
const message = document.createElement('li');
message.textContent = e.data;
messages.appendChild(message);
}
socket.onclose = function () {
console.log('WebSocket connection closed.');
setTimeout(connect, 1000);
}
socket.onerror = function (error) {
console.log('WebSocket error: ' + error.message);
}
const form = document.getElementById('sendForm');
const input = document.getElementById('messageInput');
form.addEventListener('submit', e => {
e.preventDefault();
socket.send(input.value);
input.value = '';
});
}
window.addEventListener('load', connect);
</script>
</head>
<body>
<ul id="messages"></ul>
<form id="sendForm">
<input id="messageInput" type="text"><button>Send</button>
</form>
</body>
</html>
在客户端启动后,在页面输入框内输入任意内容,再点击发送按钮,消息将被发送到服务端,而服务端收到消息后,会通过WebSocket通道将消息推送给所有已连接的客户端。
第二个示例中,我们将通过WebSocket连接模拟客户端和服务端之间的传输文件,客户端选择文件后,服务端接收文件并保存到本地。
服务端代码:
const http = require('http');
const fs = require('fs');
const crypto = require('crypto');
const websocket = require('ws');
const stream = require('stream');
const server = http.createServer((req, res) => {
//处理WebSocket握手
if (req.headers.connection === 'Upgrade' && req.headers.upgrade === 'websocket') {
const secWebSocketKey = req.headers['sec-websocket-key'];
const secWebSocketAccept = crypto
.createHash('sha1')
.update(secWebSocketKey + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', 'binary')
.digest('base64');
res.writeHead(101, {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Accept': secWebSocketAccept
});
const ws = new websocket.WebSocket({ server: server });
ws.on('connection', function (socket) {
console.log('webSocket server connected');
let writableStream;
socket.on('message', function (message) {
if (message instanceof Buffer) {
if (writableStream) {
writableStream.write(message);
}
} else {
//收到文件名
const fileName = message.toString();
writableStream = fs.createWriteStream(`./files/${fileName}`);
}
});
socket.on('close', function () {
writableStream.end(() => {
console.log('file saved successfully');
});
});
});
} else {
//处理HTTP请求
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}
});
server.listen(8080);
console.log('Server running on port 8080.');
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket File Transfer Example</title>
<script>
let socket;
function connect() {
socket = new WebSocket('ws://localhost:8080');
socket.onopen = function () {
console.log('WebSocket connection opened.');
}
socket.onmessage = function (e) {
console.log('received: ' + e.data);
if (typeof e.data === 'string') {
//接收到服务端请求文件内容的消息,开始发送文件
const file = document.getElementById('file').files[0];
const reader = new FileReader();
reader.onload = function (e) {
const buffer = e.target.result;
for (let i=0, length=buffer.byteLength; i<length; i+=1024) {
const chunk = buffer.slice(i, i+1024);
socket.send(chunk);
}
}
reader.readAsArrayBuffer(file);
//发送文件名
socket.send(file.name);
}
}
socket.onclose = function () {
console.log('WebSocket connection closed.');
}
socket.onerror = function (error) {
console.log('WebSocket error: ' + error.message);
}
}
window.addEventListener('load', connect);
</script>
</head>
<body>
<form enctype="multipart/form-data">
<input id="file" type="file">
</form>
</body>
</html>
在客户端启动后,选择任意文件,上传文件时,服务端便会接收到文件,并将文件保存到指定目录中。
这便是应用WebSocket实现的两个示例,第一个示例利用WebSocket实现客户端与服务端之间的聊天,第二个示例利用WebSocket实现了文件上传及保存的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nodejs实现WebSocket代码实例 - Python技术站