【问题标题】:Node.js: Connecting to a Server Using SocketsNode.js:使用套接字连接到服务器
【发布时间】:2011-04-27 06:37:55
【问题描述】:

我今天刚开始玩 Node.js,我想我会从我认为的简单脚本开始:通过套接字连接到服务器,发送一些数据,然后接收回来.我正在创建一个命令行实用程序。浏览器中没有任何内容。

服务器的一个例子是 memcached、beantalkd 等。看起来 net 模块是适合这项工作的工具,但我对 Node.js 的处理方式仍然有点模糊。一些帮助将不胜感激。

更新 #1

让我看看是否可以将其分解为几个较小的问题。我什至讨厌问这样的问题,但是 Node.js 文档非常稀少,而且 6 个月前编写的大多数文档已经过时了。

1) 所以我可以使用 net.stream.write() 将数据发送到远程服务器,但我不知道如何得到响应。我什至不确定如何测试 write() 何时完成,因为它不需要回调。

2) 关于整个 event.emit 的工作原理的一些线索会很棒。我认为这确实是我在整件事中缺少的关键。

更新 #2

这就是我在实现客户端程序时仍然感到困惑的地方。让我绘制一个典型的发送请求 => 获取响应系统:

1) 我将回调绑定到 net 模块以获取响应和其他事件,包括从服务器获取响应所需的绑定。

2) 我使用 stream.write() 向服务器发送请求。

3) 然后我什么也不做,因为我绑定的“数据”事件会得到服务器的响应。

这就是事情变得棘手的地方。假设我在调用绑定的“数据”事件之前调用了 stream.write() 两次。现在我有一个问题。当“数据”事件确实发生时,我如何知道它响应了 2 个请求中的哪一个?我是否保证响应将按照与请求相同的顺序进行?如果响应以不同的顺序返回怎么办?

【问题讨论】:

  • 没有太多时间提款机,但网。 nodejs.org/api.html 时钟在边栏中的 net.Server 上。你有它。一切都是基于事件的,你必须监听流的data 事件。该示例实际上更像是一个基本的回显服务器。如果你愿意,我可以稍后再为你做一些例子。
  • 如果您需要知道客户端响应的是哪个write 很重要,您可能应该在您发送/接收的数据中添加一个id 或类似的东西。但这是网络的普遍问题,与基于事件的方法无关。

标签: javascript sockets node.js


【解决方案1】:

首先,让我们弄清楚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启动服务器。

现在在传入连接的情况下会发生什么?

  1. 由于我们传递给createServer 的函数绑定到connection 事件,它现在被执行。

  2. 它通过挂钩事件的回调将connectdataend 事件侦听器添加到stream object(代表单个连接)。

  3. 之后,stream 触发connect 事件,因此在#2 处传递的函数被执行并将hello\r\n 写入流。函数如何知道它应该写入哪个流? Closures 是答案,该函数继承了它创建的范围,因此在函数内部stream 仍然引用触发我们现在所在的回调的单个连接。

  4. 1234563客户。
  5. 万一客户端关闭连接,我们在#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

这些现在从上到下执行,在它们之间不会发生任何事情。没有机会,当您在绑定到data 事件的callback 中做某事时,其他事情会发生并神奇地改变系统的状态。即使服务器上有一个新的传入连接,它的事件也会排队,它必须等待它之前的所有内容,包括您当前所在的 data 事件,完成。

【讨论】:

  • 感谢 Ivo 提供的出色示例。有机会向我展示客户端实现吗?还是把我指向一个?我一直在寻找 node-memcache 模块寻求帮助,但事件驱动模型让事情变得有点疯狂。例如,您不写入服务器并等待响应。你写入服务器,什么也不做。在某些时候,服务器会做出响应,并且您的一个事件侦听器会捕获它。但似乎你必须想出一些创造性的解决方案来处理这种方法。
  • 如果您想从节点内建立到服务器的连接,请查看net.Streamnet.createConnection,它们可以让您建立单个连接。在我的示例中,一旦有人连接到服务器,此连接就会产生类似的事件,例如 stream object
  • 我接受你的回答,因为这是一个明确的答案,我不想再浪费你的时间来帮助我。但我确实更新了我的问题,以反映一些我仍然感到困惑的领域。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2018-10-11
  • 1970-01-01
相关资源
最近更新 更多