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');
});

解释

  1. 客户端

    • 使用 fs.createReadStream 创建一个流来读取文件。
    • 按照指定的 chunkSize 分块读取文件,并通过 socket.write(chunk) 发送每个数据块。
    • 当文件读取完成后,调用 client.end() 来关闭连接。
  2. 服务端

    • 使用 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');
});

解释

  1. 服务端:服务端监听数据事件并累积到 buffer 中。当 buffer 包含一个完整的消息(这里假设以换行符 \n 结尾)时,就提取该消息并处理。
  2. 客户端:客户端连接到服务器并发送多个消息。它监听从服务器接收到的数据并打印出来。

这种方法确保即使数据被分段传输,服务端也能正确处理整个消息。

回到顶部