【发布时间】:2018-07-28 11:30:56
【问题描述】:
我有两个正在相互通信的进程 - 客户端是 C# 控制台应用程序。服务器是一个 Node.js 应用程序,它使用了“网络”模块 (TCP)。
我需要完成的过程是:
- C# 客户端连接到 Node.js 服务器并发送 HTML。
- Node.js 接收 HTML 数据,并生成 PDF(使用 Puppeteer)。
- Node.js 服务器将 PDF 作为字节数组发送到 C# 客户端。
这工作顺利直到步骤 1 中的有效负载达到一定大小。那时,数据开始被分成多个块。块的组合大小等于最初发送的有效负载,因此它们都到达了服务器。
这会导致问题,因为生成 PDF 的代码位于 socket.on(data) 事件中。由于数据被多次接收,服务器正在创建多个 PDF,并且没有一个是完整的。
我读过的一些帖子建议使用 socket.on(end) 事件,但该事件没有触发,因为连接没有关闭 - 我需要保持连接打开,以便执行第 3 步。
我的第一个想法是“我需要增加缓冲区大小以便发送整个文件”,但经过一些研究后,我决定不这样做,因为拆分数据似乎是预期的行为。
我的问题是:我如何知道整个有效负载何时到达 Node.js 服务器?
- 我可以利用 Node.js 中的套接字事件或其他事件吗?
- 我可以检查发送的
data对象的属性吗? - 有没有办法让客户端“发出”它已完成发送数据的“信号”?
这似乎是一个常见的场景,所以我正在寻找一些最佳实践,因为我对 Node.js 比较陌生。
更新
这是导致创建多个 PDF 的(缩写)代码,因为数据被多次接收:
const net = require('net');
const PORT = 8080;
const ADDRESS = '127.0.0.1';
const server = net.createServer(onConnectionOpen);
server.listen(PORT, ADDRESS);
function onConnectionOpen(socket) {
socket.on('data', (data) => {
const folderName = 'reports';
var fileName = functions.getRandomString(50) + '.pdf';
var fullPath = process.cwd() + '\\' + folderName + '\\' + fileName;
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setContent(data.toString());
const pdf = await page.pdf({ path: fullPath, format: 'Letter' });
console.log('Total bytes returned: ' + pdf.length);
socket.write(pdf);
await browser.close();
})();
})
socket.on('end', () => {
socket.destroy();
})
}
我已尝试将 Puppeteer 和 socket.write(...) 移动到 socket.on('end'),但该代码在生成 PDF 后无法运行,因为连接仍处于打开状态。
【问题讨论】:
-
如果您展示用于接收数据的实际 node.js 代码,我们可以提供更好的帮助。
-
超过一定大小的数据可能会以块的形式到达。您必须能够检测到最后一个块何时以某种方式到达。如果出于某种原因您不能使用
end事件(我仍然不明白为什么,并且这是了解流何时完成向您发送数据的常用方法),那么您必须设计一些其他方式来您发送数据以了解最后一个块何时到达(可能发送一些您可以观察的分隔符)。那是你的责任。 -
我已经更新了代码示例。我不能使用 end 事件的原因是因为根据我的测试和我在 nodejs.org 上阅读的内容,当连接关闭时会触发 end 事件。我保持连接打开,因为 node.js 服务接收到数据后,它需要在连接上发回数据。