Nodejs 如何设置dgram UDP 【接收】的数据包字节数?

Nodejs 如何设置dgram UDP 【接收】的数据包字节数?

比如在PHP中可以这样:

fread($socket, 4000) 一次可以完整读取。

nodejs var udp = dgram.createSocket(“udp4”); … udp.on(‘message’, function(data, info) { 接收就分成了2个包:

<Buffer 00 00 00 ff ef 00 00 0 36 62 70 70 00 31 00 5f 5f 73 …> length: 1400

<Buffer 65 6e 63 ff 00 b5 00 0 68 00 30 00 6d 70 5f 77 69 6e …> length: 532

有没有办法设置一次接收的字节数,让他一次性接完?

因为第三方服务端,我无法修改发包程序,而且第一个包开头有标记,第二个包无标记,没法判断合并。


2 回复

在 Node.js 中使用 dgram 模块处理 UDP 数据包时,默认情况下,dgram 并不支持直接设置单次接收的数据包大小。不过,你可以通过调整数据包的处理逻辑来确保数据能够被完整接收。

如果你希望一次性接收完整的数据包,可以通过维护一个缓冲区来累积接收到的数据,并在接收到完整的数据包后进行处理。以下是一个示例代码,展示了如何实现这一点:

const dgram = require('dgram');

// 创建 UDP 套接字
const server = dgram.createSocket('udp4');

// 缓冲区用于累积接收到的数据
let buffer = Buffer.alloc(0);

server.on('listening', () => {
    const address = server.address();
    console.log(`UDP Server listening on ${address.address}:${address.port}`);
});

server.on('message', (data, rinfo) => {
    // 将新接收到的数据追加到缓冲区
    buffer = Buffer.concat([buffer, data]);

    // 检查是否接收到完整的数据包
    while (true) {
        if (buffer.length >= 4 && buffer[0] === 0x00 && buffer[1] === 0x00 && buffer[2] === 0x00 && buffer[3] === 0xff) {
            // 找到完整的数据包
            const packetLength = buffer.readUInt32BE(4); // 获取数据包长度
            if (buffer.length >= packetLength + 8) {
                // 如果缓冲区中的数据足够长,则提取完整的数据包
                const packet = buffer.slice(0, packetLength + 8);
                console.log('Received complete packet:', packet);

                // 移除已处理的数据包
                buffer = buffer.slice(packetLength + 8);

                // 处理数据包(此处仅打印)
                processPacket(packet);
            } else {
                // 数据包不完整,退出循环等待更多数据
                break;
            }
        } else {
            // 数据包不完整,退出循环等待更多数据
            break;
        }
    }
});

server.on('error', (err) => {
    console.error(`Server error:\n${err.stack}`);
    server.close();
});

function processPacket(packet) {
    // 这里可以添加处理数据包的逻辑
    console.log('Processing packet:', packet.toString());
}

server.bind(41234); // 绑定端口

在这个示例中:

  1. 我们创建了一个 UDP 服务器并监听指定的端口。
  2. 使用一个 buffer 变量来累积接收到的数据。
  3. 在接收到数据时,将新数据追加到 buffer
  4. 检查 buffer 中是否有完整的数据包。如果有,提取并处理该数据包。
  5. 如果数据包不完整,则继续等待更多数据。

这种方法可以确保即使数据包被分割成多个部分,也能正确地接收和处理它们。


在Node.js中使用dgram模块处理UDP数据包时,默认情况下,当接收到数据时,会触发message事件,并将整个数据包作为参数传递给事件处理器。dgram模块本身没有直接提供设置单次接收字节数的功能,因为UDP协议本身不保证数据包的大小或顺序。

但是,可以通过自定义逻辑来确保数据被正确地组合在一起。这通常涉及跟踪每个数据包并将其按顺序组合。以下是一个简单的示例,展示如何实现这一点:

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

let buffer = Buffer.alloc(0); // 用于存储所有数据包

server.on('message', (chunk, rinfo) => {
    buffer = Buffer.concat([buffer, chunk]);
    
    // 假设你知道整个消息的最大长度,或者你可以根据你的业务逻辑来确定何时停止接收数据
    const maxLength = 4000; // 例如,假设最大长度为4000字节
    if (buffer.length >= maxLength) {
        console.log("Received full message:", buffer.toString());
        // 处理数据后重置缓冲区
        buffer = Buffer.alloc(0);
    }
});

server.on('listening', () => {
    const address = server.address();
    console.log(`Server listening on ${address.address}:${address.port}`);
});

server.bind(41234); // 绑定到一个端口

在这个例子中,我们创建了一个buffer来累积所有到达的数据。当缓冲区的大小达到或超过预设的最大值(在这个例子中为4000字节)时,我们就认为已经收到了完整的消息,并对其进行处理。处理完之后,我们会重置缓冲区以准备接收新的数据。

请注意,这种方法依赖于你能够预先知道或估算出消息的最大长度。如果无法确定最大长度,你可能需要实现更复杂的逻辑来识别消息的边界,例如通过查找特定的标记或结束符。

回到顶部