Nodejs TCP 客户端发送大量数据给服务端
Nodejs TCP 客户端发送大量数据给服务端
发给客户端是这样的:tcp_client.write(file_content); 服务端接收: socket.on(‘data’,function(data){ console.log(i++);
socket.write('hello');
//返回给客户端
});
问题是:on(‘data’)会多次执行,有什么办法解决吗?
9 回复
在使用 Node.js 的 TCP 通信时,处理大文件传输是一个常见的需求。由于 socket.on('data')
事件会在接收到一部分数据时触发多次,我们需要确保能够正确地拼接这些数据片段,并且高效地处理它们。
示例代码
TCP 客户端
首先,客户端需要将文件内容分块发送:
const net = require('net');
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {
console.log('Connected to server');
});
// 读取文件并分块发送
const fs = require('fs');
const chunkSize = 1024 * 1024; // 每次发送1MB的数据
let fileStream = fs.createReadStream('large_file.txt', { highWaterMark: chunkSize });
fileStream.on('open', () => {
console.log('File opened');
});
fileStream.on('data', (chunk) => {
client.write(chunk);
});
fileStream.on('end', () => {
client.end(); // 文件发送完毕后关闭连接
});
TCP 服务端
服务端需要接收这些分块数据并拼接起来:
const net = require('net');
const server = net.createServer((socket) => {
let receivedData = Buffer.alloc(0);
socket.on('data', (data) => {
receivedData = Buffer.concat([receivedData, data]);
console.log(`Received ${receivedData.length} bytes`);
});
socket.on('end', () => {
console.log('Received all data');
console.log(receivedData.toString()); // 处理完整数据
});
});
server.listen(8080, () => {
console.log('Server listening on port 8080');
});
解释
-
客户端:
- 使用
fs.createReadStream
创建一个流来读取文件。 - 按照指定的
chunkSize
分块读取文件,并通过socket.write(chunk)
发送每个数据块。 - 当文件读取完成后,调用
client.end()
来关闭连接。
- 使用
-
服务端:
- 使用
Buffer.concat
方法来拼接每次接收到的数据块。 - 在接收到所有数据后(通过监听
'end'
事件),可以处理完整的数据。
- 使用
这种方法确保了即使文件非常大,也能有效地分块发送和接收,同时避免了数据片段丢失或乱序的问题。
自己粘包。。必须的。
服务端怎么接受数据?
事件队列
严重怀疑你重复绑定了事件
ExBuffer解决该问题
var buffers = [];
socket.on('data', function(chunk) {
buffers.push(chunk);
})
socket.on('end', function() {
var data = Buffer.concat(buffers).toString('utf8');
})
我是常连接的
在这个场景中,socket.on('data')
多次执行是因为每次接收到的数据可能只是整个消息的一部分。为了解决这个问题,你可以使用缓冲区来累积这些部分,并在接收到完整的消息后进行处理。
示例代码
服务端代码
const net = require('net');
const server = net.createServer((socket) => {
let buffer = '';
socket.on('data', (data) => {
buffer += data.toString();
// 假设每个消息以换行符结尾
while (buffer.includes('\n')) {
const index = buffer.indexOf('\n');
const message = buffer.substring(0, index + 1);
buffer = buffer.substring(index + 1);
console.log(`Received: ${message}`);
socket.write(`Server received: ${message}`);
}
});
socket.on('end', () => {
console.log('Client disconnected');
});
});
server.listen(3000, () => {
console.log('Server listening on port 3000');
});
客户端代码
const net = require('net');
const client = new net.Socket();
client.connect(3000, 'localhost', () => {
console.log('Connected to server');
// 发送大量数据
for (let i = 0; i < 10; i++) {
client.write(`Message ${i}\n`);
}
});
client.on('data', (data) => {
console.log(`Received from server: ${data.toString()}`);
});
client.on('close', () => {
console.log('Connection closed');
});
解释
- 服务端:服务端监听数据事件并累积到
buffer
中。当buffer
包含一个完整的消息(这里假设以换行符\n
结尾)时,就提取该消息并处理。 - 客户端:客户端连接到服务器并发送多个消息。它监听从服务器接收到的数据并打印出来。
这种方法确保即使数据被分段传输,服务端也能正确处理整个消息。