代码之家  ›  专栏  ›  技术社区  ›  mellowsoon

node.js:使用套接字连接到服务器

  •  1
  • mellowsoon  · 技术社区  · 14 年前

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

    服务器的一个例子是memcached、beanstack等。网络模块似乎是适合该工作的工具,但我对node.js的工作方式仍然有点模糊。希望能得到一些帮助。

    更新第1号

    让我看看我能不能把这个问题分解成几个小问题。我甚至不喜欢问这样的问题,但是node.js文档非常稀少,6个月前编写的大多数文档已经过时了。

    1)所以我可以使用net.stream.write()将数据发送到远程服务器,但我不知道如何返回响应。我甚至不知道如何在write()完成时进行测试,因为它不接受回调。

    2)一些关于整个事件的线索。发射物是如何工作的将是伟大的。我认为这才是我在这整件事中所缺少的关键。

    更新第2号

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

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

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

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

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

    1 回复  |  直到 14 年前
        1
  •  8
  •   Ivo Wetzel    14 年前

    首先,让我们弄清楚 EventEmitter 是。因此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');
    

    所以我们创建服务器并将其传递给 回调函数 ,此函数尚未执行。在这里传递函数基本上是为 connection 服务器对象的事件。之后,我们启动服务器 #5 .

    现在,如果是传入连接,会发生什么情况?

    1. 因为我们传递给 createServer 被束缚在 连接 事件,它现在被执行。

    2. 它增加了 connect , data end 事件侦听器 stream object (表示单个连接)通过连接事件的回调。

    3. 之后, stream 开火 连接 事件,因此函数在 #2 执行并写入 hello\r\n 流向溪流。函数如何知道应该写入哪个流? Closures 答案是,函数继承了它在其中创建的作用域,因此在函数内部 流动 仍在引用触发这个回调的单个连接。

    4. 现在,客户机通过连接发送一些数据,这使得 流动 对象调用它的 数据 事件,因为我们在 #3 现在,我们将传入的数据回送到客户机。

    5. 如果客户机关闭了连接,我们所绑定的函数 #4 被调用,写入 goodbye\r\n 在那之后,我们这边的连接就关闭了。

    这能让事情更清楚一点吗?好吧,这确实让整个事情变得容易多了。就像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 绑定到 数据 事件,会有其他事情发生,并神奇地改变系统的状态。即使服务器上有一个新的传入连接,它的事件也将被排队,并且必须等到所有事情发生之前,包括 数据 您当前所在的活动,结束。