我今天刚刚开始使用Node.js,并且认为我会从我认为简单的脚本开始:通过套接字连接到服务器,发送一些数据,并将其接收回来.我正在创建一个命令行实用程序.浏览器中没有任何内容.
服务器的一个例子是memcached,beanstalkd等.看来net模块是工作的正确工具,但我对Node.js的工作方式仍然有点模糊.一些帮助将不胜感激.
更新#1
让我看看我是否可以将其分解为几个较小的问题.我讨厌甚至提出这样的问题,但Node.js文档非常稀疏,大多数6个月前编写的文档已经过时了.
1)所以我可以使用net.stream.write()将数据发送到远程服务器,但我不知道如何获得响应.我甚至不确定如何在write()完成时进行测试,因为它不需要回调.
2)关于整个事件如何发挥作用的一些线索将是伟大的.我认为这是我在这些事情中缺少的关键石头.
更新#2
这是我在实施客户端程序时仍然感到困惑的地方.让我绘制一个典型的send request => get response system:
1)我将回调绑定到net模块以获取响应和其他事件,包括从服务器获取响应所需的绑定.
2)我使用stream.write()向服务器发送请求.
3)然后我什么都不做,因为我的绑定"数据"事件将从服务器获得响应.
事情变得棘手.假设我在调用绑定的"data"事件之前调用了两次 stream.write().现在我有一个问题.当"数据"事件确实发生时,我怎么知道这2个请求中的哪一个是响应?我保证答复将按照与请求相同的顺序进行吗?如果回复以不同的顺序返回怎么办?
首先,让我们弄清楚它EventEmitter
是什么.JavaScript和Node.js是asynchronous
.这意味着,您不必等待服务器对象上的传入连接,而是向对象添加一个listener
并传递给它callback function
,然后,在事件发生时"尽快"执行.
在这里和那里仍然在等待,但是这已经被抽象了.
我们来看看这个简单的例子:
// #1) create a new server object, and pass it a function as the callback var server = net.createServer(function (stream) { // #2) register a callback for the 'connect' event stream.on('connect', function () { stream.write('hello\r\n'); // as }); // #3) register a callback for the 'data' event stream.on('data', function (data) { stream.write(data); }); // #4) register a callback for the 'end' event stream.on('end', function () { stream.write('goodbye\r\n'); stream.end(); }); }); // #5) make the server listen on localhost:8124 server.listen(8124, 'localhost');
所以我们创建服务器并传递它callback function
,此函数尚未执行.在此处传递函数基本上是为connection
服务器对象的事件添加侦听器的快捷方式.之后我们启动服务器#5
.
现在,在传入连接的情况下会发生什么?
由于我们传递给的函数createServer
绑定到connection
事件,现在它被执行.
它添加了connect
,data
并且end
事件侦听器来stream object
(代表单独的连接)通过挂钩回调的事件.
之后,stream
触发connect
事件,因此传递的函数将#2
被执行并写入hello\r\n
流.函数如何知道应该写入哪个流?闭包是答案,函数继承了它创建的范围,因此函数内部stream
仍然引用了触发我们现在所处的回调的单个连接.
现在客户端通过连接发送一些数据,这使得stream
对象调用它的data
事件,因为我们将一个函数绑定到此事件,#3
现在我们将传入的数据回送给客户端.
在客户端关闭连接的情况下,我们绑定的函数#4
被调用,写入goodbye\r\n
并在此之后关闭我们方的连接.
这会让事情变得更清楚吗?好吧,它确实让整个事情变得更加容易.Node就像JavaScript里面的浏览器一样single threaded
.在给定的时间点只发生一件事.
为了简单描述,所有这些都callbacks
最终在一个全局队列中,然后一个接一个地被调用,所以这个队列可能(抽象)看起来像这样:
| connection event for a new stream | data event for stream #12 | callback set via setTimeout v close event of yet another stream
这些现在从上到下执行,在这些之间不会发生任何事情.没有机会,当你在事件的callback
约束data
下做某事时,会发生其他事情并神奇地改变系统的状态.即使服务器上有新的传入连接,它的事件也会排队,它必须等到它之前的所有内容,包括data
你当前所在的事件完成.