NodeJS流媒体 - 什么是大惊小怪?

时间:2016-02-06 23:31:58

标签: node.js sockets tcp stream

请原谅我这个愚蠢的问题,但我对NodeJS中流媒体的大惊小怪感到有点困惑。

我知道流式传输允许我们一次发送大量数据,从而改善最终用户的体验

但是,这不是数据在互联网上传输的标准方式吗?哪里,在客户端和服务器之间建立套接字连接,数据是通过数据包发送的?

Socket == stream&&和数据包==块,对吧?

1 个答案:

答案 0 :(得分:2)

这根本不是重点。

您通过TCP / IP通信以点对点的方式传送了一系列数据包。

但是,在开始播放之前,请考虑允许您查看文件部分的网站,以及迫使您等待整个文件准备就绪的网站。

不同之处在于客户端和服务器同意的是“完整”文档。

在最后一个示例中,该文件是完整的文档。 服务器无法(/不愿意)提供比完整文件更细粒度的文档;因此,您的浏览器必须等到整个文件下载完毕后才能使用它。

在另一个Universe中,一个完整的“文档”可能是一组字节,它们与头信息一起传回,指定这些字节所在的总文件中的位置,允许搜索文档,当你有部分时播放内容,等等。 当播放器耗尽缓冲内容时,它将寻找下一部分,该部分恰好是由另一组字节组成的资源,从其当前内容之后的字节开始。

这与Node没什么关系,更多的是与HTTP1.1

有关

其他形式的插槽连接(WebSockets,UDP等)有不同的行为和期望。

与Node无关,尽管Node的流确实能够轻松支持服务器之间以及某种形式的客户端之间的流式通信,无论是否通过HTTP。

好的,所以覆盖并且不在路上...... 那么节点“流”是什么,如果不是特别关于分块通信呢?

要掌握这一点,最简单的方法是从基于set(/ collection)的编程概念开始。

曾几何时,如果我有一个我希望加倍的数字列表,我可能会写出如下内容:

var numbers = [1, 2, 3];
var number;
var doubles = [];
var i = 0,
    l = numbers.length;

for (; i < l; i += 1) {
  number = numbers[i];
  doubles.push( number * 2 );
}

但是,现在,我使用.map来删除所有的循环管理,而只关注我想要应用于每个元素的微小的原子操作:

const numbers = [1, 2, 3];
const doubles = numbers.map(x => x * 2);

右? 这大大降低了复杂性。当然,如果我想继续将额外的变换链接到后面,我可以。

numbers
  .map(double)
  .map(add1)
  .filter(gt5)
  .map( ... ) // etc

现在你看到更多功能性,基于集合的编程就是一次声明一个单独的操作,一次只能在一个元素上声明... ......溪流进来的地方?

嗯......如果你正在映射和过滤(和减少)的数组没有完成怎么办? 如果在系统运行的时候由其他进程异步填充该怎么办?

它可能是通过分块的HTTP1.1流量填充的,当然......但是这远不是必需的。它可以由超时,系统操作,数据库或太阳下的任何其他东西填充。

如果我有一个神奇的服务,它给了我一个流,我可能会这样使用它:

// returns a stream which fires on *every* returned row
db.streamQuery( "select * from ........" )
  // turned into domain objects in your system
  .pipe( transformRecordIntoObject )
  // remove private data (DB keys, admin properties, whatever)
  .pipe( removeInternalObjectProperties )
  // remove entries which aren't wanted/helpful, for one reason or another
  .pipe( filterOutUnwantedEntries )
  // buffer entries up, to serve an array of 100 at a time
  .pipe( bufferEvery100AsJSON )
  // send the JSON of 100 results (at a time) straight to the client who requested them
  .pipe( res );

正如您所看到的,流本身(提供.pipe,它接受​​连接流)与HTTP通信几乎没有关系...
...说,它们非常适合,并且您在HTTP请求中拥有的reqres对象分别是可读写的流,因此,您可以从以这种方式对他们说。

我故意跳过具体的实现细节,以及尾端的具体通信要求,我在网上发送了一些JSON ...... ...这对于典型的HTTP响应(包括基于范围的内容流)需要更多的工作,但是对于比如说ServerSent事件而言,不需要更多的工作。

我希望这有助于解释您可能期望的内容与您正在阅读的内容之间的一些差异......以及流式套接字通信和可能的功能流之间的一些交叉可以在Node和Scala中找到,在Bash | Powershell等中使用终端命令管道,以及其他一些地方。