如何通过response.write在node.js中正确发送缓冲区?

如何通过response.write在node.js中正确发送缓冲区?,node.js,node.js-buffer,Node.js,Node.js Buffer,我正在尝试从node.js服务器发送二进制内容。为此,我分配一个缓冲区并用我的内容填充缓冲区,然后对其调用response.write()。一旦它返回,我就用新内容重用缓冲区。然而,由于某些原因,它似乎不能正常工作 以下是服务器代码: const http = require('http'); async function sendChunk( response, outbuf ) { console.log( "Sending buffer: %s", outbuf );

我正在尝试从node.js服务器发送二进制内容。为此,我分配一个缓冲区并用我的内容填充缓冲区,然后对其调用
response.write()
。一旦它返回,我就用新内容重用缓冲区。然而,由于某些原因,它似乎不能正常工作

以下是服务器代码:

const http = require('http');

async function sendChunk( response, outbuf )
{
    console.log( "Sending buffer: %s", outbuf );

    // Send the buffer out. If it returns false, 
    // this means the kernel buffers are full,
    // and we have to wait until they are available.
    if ( await response.write( outbuf ) === false )
    {
        await new Promise(resolve => response.once('drain', ()=>{
            resolve();
        }));
    }
}

async function sendData( response )
{
    let outbuf = Buffer.alloc( 20 );

    for ( let count = 0x45; count < 0x50; count++ )
    {
        for ( let i = 0; i < outbuf.length; i++ )
        {
            outbuf[i] = count;
        }

        await sendChunk( response, outbuf );
    }
}


function webRequestHandler( request, response )
{
    let body = [];

    request.on('error', (err) => {
        console.error(err);
        return;

    });

    request.on('data', (chunk) => {
        body.push(chunk);
    });

    response.on('error', (err) => {
        console.error( "Error sending response: %s", err);
        return;
    });

    // A whole body collected - process it
    request.on('end', async () => {

        // Handle the update; can return an error message
        response.setHeader('Content-Type', 'text/plain');
        await sendData( response );
        response.end();
    });
}

const webserver = http.createServer( webRequestHandler );

// Create the web service
webserver.on('error', function (err) {
    console.log("[" + process.pid + "] " + JSON.stringify(err));
    process.exit();
});

webserver.listen( { "host" : "127.0.0.1", "port" : 5252 }, () => {
    console.log( "Server running" );
});
然而,客户收到的却是完全不同的东西:

> curl http://localhost:5252/
EEEEEEEEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
这是怎么回事?如果我在sendChunk中创建一个新的缓冲区(它是EXPUFF的一个副本),它确实可以工作。然而,这似乎是对RAM的浪费,对于来自C背景的人来说没有什么意义,而且一旦你在套接字上调用
send()
,数据就被复制了,你可以随心所欲地重用源缓冲区

node.js的工作方式不同吗?我是否需要为response.write()创建一个专用缓冲区,在调用write后,即使write已返回,并且我等待
drain
事件,也不能再对其进行操作?

我已经发布了一条重要的评论,该评论被关闭:

您应该将回调传递给.write(),以了解节点何时启动 完成了那块内存,而不是依赖于“drain” 事件

一旦进行了更改,您将在 你在期待

实际上,一旦
sendcunk
函数更改如下:

Sending buffer: EEEEEEEEEEEEEEEEEEEE
Sending buffer: FFFFFFFFFFFFFFFFFFFF
Sending buffer: GGGGGGGGGGGGGGGGGGGG
Sending buffer: HHHHHHHHHHHHHHHHHHHH
Sending buffer: IIIIIIIIIIIIIIIIIIII
Sending buffer: JJJJJJJJJJJJJJJJJJJJ
Sending buffer: KKKKKKKKKKKKKKKKKKKK
Sending buffer: LLLLLLLLLLLLLLLLLLLL
Sending buffer: MMMMMMMMMMMMMMMMMMMM
Sending buffer: NNNNNNNNNNNNNNNNNNNN
Sending buffer: OOOOOOOOOOOOOOOOOOOO
async function sendChunk( response, outbuf )
{
    return new Promise( function( resolve, reject) {

        if ( response.write( outbuf, ()=>{ resolve(); } ) === false )
        {
            console.log( "Draining buffer" );
            response.once('drain', ()=>{
                resolve();
            });
        }
    });
}
所以我们只在函数回调中解决它,问题就消失了。这里的核心问题是,
response.write
是不可等待的,并且在调用回调之前返回

我应该更仔细地阅读文档。

我发布了一条重要的评论:

您应该将回调传递给.write(),以了解节点何时启动 完成了那块内存,而不是依赖于“drain” 事件

一旦进行了更改,您将在 你在期待

实际上,一旦
sendcunk
函数更改如下:

Sending buffer: EEEEEEEEEEEEEEEEEEEE
Sending buffer: FFFFFFFFFFFFFFFFFFFF
Sending buffer: GGGGGGGGGGGGGGGGGGGG
Sending buffer: HHHHHHHHHHHHHHHHHHHH
Sending buffer: IIIIIIIIIIIIIIIIIIII
Sending buffer: JJJJJJJJJJJJJJJJJJJJ
Sending buffer: KKKKKKKKKKKKKKKKKKKK
Sending buffer: LLLLLLLLLLLLLLLLLLLL
Sending buffer: MMMMMMMMMMMMMMMMMMMM
Sending buffer: NNNNNNNNNNNNNNNNNNNN
Sending buffer: OOOOOOOOOOOOOOOOOOOO
async function sendChunk( response, outbuf )
{
    return new Promise( function( resolve, reject) {

        if ( response.write( outbuf, ()=>{ resolve(); } ) === false )
        {
            console.log( "Draining buffer" );
            response.once('drain', ()=>{
                resolve();
            });
        }
    });
}
所以我们只在函数回调中解决它,问题就消失了。这里的核心问题是,
response.write
是不可等待的,并且在调用回调之前返回


应该更仔细地阅读文档。

我不确定您的实际问题是什么,但您不能使用
等待
响应。编写
。这是因为它是一个流,而不是一个承诺(流和承诺都只是处理异步操作的设计模式,但它们有不同的API,例如承诺有async/await)。诚然,在这种情况下,它是一个不可操作的(等待什么也不做),但它可能会误导你的反应。写入回调,但它没有改变任何东西,所以我怀疑问题是否存在。谢谢你的评论。我不确定你的实际问题是什么,但是你不能用
等待
响应。写
。这是因为它是一个流,而不是一个承诺(流和承诺都只是处理异步操作的设计模式,但它们有不同的API,例如承诺有async/await)。诚然,在这种情况下,它是一个不可操作的(等待什么也不做),但它可能会误导你的反应。写入回调,但它没有改变任何东西,所以我怀疑问题是否存在。谢谢你的评论。