我正在尝试从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/
测试时,服务器将打印以下内容:
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
但是客户收到的东西完全不同:
> curl http://localhost:5252/
EEEEEEEEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
这是怎么回事?如果在sendChunk中创建一个新缓冲区(这是outbuf的副本),它将起作用。但是,这似乎浪费了RAM,对于来自C背景的人来说并没有什么意义,一旦在套接字上调用send()
,就已经复制了数据,并且可以在使用时重新使用源缓冲区希望。
node.js的工作方式不同吗?我是否需要为response.write()创建一个专用缓冲区,即使写返回并且我等待了drain
事件,调用写操作后也无法再触摸它吗?
答案 0 :(得分:0)
我发布了the bug report,并以一条重要的评论告终:
您应该将回调传递给.write()才能知道节点何时处于 完成那块内存,而不是依靠“流失” 事件。
进行更改后,您将在客户端上看到以下输出: 您正在期待。
实际上,sendChunk
函数的更改如下:
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
不可等待,并且在调用回调之前返回。
应该更仔细地阅读文档。