node js "response.on('data', func(chunk))" 是否保证chunk边界
Does node js "response.on('data', func(chunk))" guarantee the chunk boundary
我正在尝试实现我的节点 js 服务以使用 http 流(传输编码:分块)发送回响应。
我使用 "response.on('data', func(chunk))" 接收从服务发回的每个块,现在可以正常工作了。
我的问题是,"response.on('data', func(chunk))" 是否保证回调中的块与服务发送的块完全相同? (或者它可以组合多个服务发送块并仅调用一次回调,或者将单个服务发送块拆分成多个块并多次调用回调?)
谢谢
迈克尔
My question is that, does the "response.on('data', func(chunk))" guarantee that the chunks in the callback are exactly the same chunks that the service sends?
没有。流对块边界的保证为零。边界实际上可以是任何地方。
or it may combine multiple service sent chunks and invoke the callback only once
是的,可能。
or split a single service sent chunk into pieces and invoke the callback multiple times
是的,可能。
如果您必须处理通常不是最适合流的离散数据片段(例如特定数据块),那么您需要在流中创建描述,告诉您要处理的块在哪里进程启动和停止,因此您可以读取和缓冲一个块,直到到达块的末尾,然后处理整个块,即使该块跨越两个或多个实际 data
事件。
有很多不同的方法来描述流中的特定数据块,使用哪种技术完全取决于数据的类型。最简单的描述示例是在文本文件中描述行的 CRLF。还有许多其他方法可以做到这一点。例如,在二进制工作中,您可以流式传输一个 header,其中包含一个内容长度,该内容长度告诉您在块结束之前准确预期有多少字节。 MIME 创建唯一的字符串标记来描述部分。有很多不同的方法可以做到这一点,具体取决于数据的情况。
仅供参考,如果数据的写入者(在流的另一端)写入了一大块数据,然后暂停了一会儿(足够长的时间让大块物理地通过网络发送),然后写入另一块数据,然后再次暂停,然后接收者可能会立即将每个块放在一起。但是,这绝不是保证,也不应该指望。传输中的任何扰动都可能很容易导致延迟或重传,最终可能 co-mingling 来自单独发送的数据块的数据,因此在给定的 data
事件中会接收到多个数据块。同样,如果发送的数据变大或路径中存在传输中断或其他网络基础设施导致数据被分解成更小的部分,则可以在多个 data
事件中接收单个数据块。
如果您需要在处理之前收集特定的数据块,那么您需要拥有自己的代码,在数据到达时将该数据块组装到缓冲区中,并在您拥有整个数据块时进行识别,然后处理该数据块.该代码需要处理所有这些情况:
- 一个块在多个
data
事件中到达
- 一个
data
事件包含多个块或多个块的一部分
- 到达
data
事件的边界与您的块的边界不同(例如,您的块被分成多个 data
事件和下一个 data
事件可能包含您的块的结尾和下一个块的开始)。
仅供参考,创建自己的流子类通常很有用,它可以自动处理数据中的边界,然后在它具有完全形成的 "chunk" 数据时发出自己的消息。它通常必须使用内部缓冲区和边界检测来实现它。
例如,有很多模块实现逐行读取文本流。他们缓冲来自 data
事件的数据,将其分成整行(保留最后一行可能不是整行的额外部分),然后为每个到达的行发出自己的 line
事件.
您可能想为自己的块数据类型做类似的事情。这样一来,您就可以以更简单的方式使用派生流,它只会发出整个块,并且您编写的使用 object 的代码会简单得多,因为您将集中块检测逻辑,因此您的其余代码不必担心。
我正在尝试实现我的节点 js 服务以使用 http 流(传输编码:分块)发送回响应。
我使用 "response.on('data', func(chunk))" 接收从服务发回的每个块,现在可以正常工作了。
我的问题是,"response.on('data', func(chunk))" 是否保证回调中的块与服务发送的块完全相同? (或者它可以组合多个服务发送块并仅调用一次回调,或者将单个服务发送块拆分成多个块并多次调用回调?)
谢谢 迈克尔
My question is that, does the "response.on('data', func(chunk))" guarantee that the chunks in the callback are exactly the same chunks that the service sends?
没有。流对块边界的保证为零。边界实际上可以是任何地方。
or it may combine multiple service sent chunks and invoke the callback only once
是的,可能。
or split a single service sent chunk into pieces and invoke the callback multiple times
是的,可能。
如果您必须处理通常不是最适合流的离散数据片段(例如特定数据块),那么您需要在流中创建描述,告诉您要处理的块在哪里进程启动和停止,因此您可以读取和缓冲一个块,直到到达块的末尾,然后处理整个块,即使该块跨越两个或多个实际 data
事件。
有很多不同的方法来描述流中的特定数据块,使用哪种技术完全取决于数据的类型。最简单的描述示例是在文本文件中描述行的 CRLF。还有许多其他方法可以做到这一点。例如,在二进制工作中,您可以流式传输一个 header,其中包含一个内容长度,该内容长度告诉您在块结束之前准确预期有多少字节。 MIME 创建唯一的字符串标记来描述部分。有很多不同的方法可以做到这一点,具体取决于数据的情况。
仅供参考,如果数据的写入者(在流的另一端)写入了一大块数据,然后暂停了一会儿(足够长的时间让大块物理地通过网络发送),然后写入另一块数据,然后再次暂停,然后接收者可能会立即将每个块放在一起。但是,这绝不是保证,也不应该指望。传输中的任何扰动都可能很容易导致延迟或重传,最终可能 co-mingling 来自单独发送的数据块的数据,因此在给定的 data
事件中会接收到多个数据块。同样,如果发送的数据变大或路径中存在传输中断或其他网络基础设施导致数据被分解成更小的部分,则可以在多个 data
事件中接收单个数据块。
如果您需要在处理之前收集特定的数据块,那么您需要拥有自己的代码,在数据到达时将该数据块组装到缓冲区中,并在您拥有整个数据块时进行识别,然后处理该数据块.该代码需要处理所有这些情况:
- 一个块在多个
data
事件中到达 - 一个
data
事件包含多个块或多个块的一部分 - 到达
data
事件的边界与您的块的边界不同(例如,您的块被分成多个data
事件和下一个data
事件可能包含您的块的结尾和下一个块的开始)。
仅供参考,创建自己的流子类通常很有用,它可以自动处理数据中的边界,然后在它具有完全形成的 "chunk" 数据时发出自己的消息。它通常必须使用内部缓冲区和边界检测来实现它。
例如,有很多模块实现逐行读取文本流。他们缓冲来自 data
事件的数据,将其分成整行(保留最后一行可能不是整行的额外部分),然后为每个到达的行发出自己的 line
事件.
您可能想为自己的块数据类型做类似的事情。这样一来,您就可以以更简单的方式使用派生流,它只会发出整个块,并且您编写的使用 object 的代码会简单得多,因为您将集中块检测逻辑,因此您的其余代码不必担心。