Node.js:使用套接字连接到服务器 [英] Node.js: Connecting to a Server Using Sockets

查看:52
本文介绍了Node.js:使用套接字连接到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天才刚开始使用Node.js,以为我会以一个简单的脚本开始:通过套接字连接到服务器,然后发送一些数据,然后将其接收回来.我正在创建一个命令行实用程序.浏览器中什么都没有.

服务器的示例是memcached,beanstalkd等.似乎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个请求中的哪个是响应?我是否保证响应将按照与请求相同的顺序进行?如果响应以不同顺序返回怎么办?

解决方案

首先,让我们弄清楚什么是 EventEmitter .JavaScript,因此Node.js是异步.这意味着,不必等待服务器对象上的传入连接,您只需向对象添加 listener ,然后将其传递给 callback函数,然后,"在事件发生时被执行.

在后台仍在等待,但是已经从您那里抽象出来了.

让我们看一下这个简单的例子:

 //#1)创建一个新的服务器对象,并将其作为回调函数传递给它var server = net.createServer(function(stream){//#2)为'connect'事件注册一个回调stream.on('connect',function(){stream.write('hello \ r \ n');//作为});//#3)注册数据"事件的回调stream.on('data',function(data){stream.write(data);});//#4)为'end'事件注册一个回调stream.on('end',function(){stream.write('再见\ r \ n');stream.end();});});//#5)使服务器在localhost:8124上侦听server.listen(8124,'localhost'); 

因此,我们创建服务器并将其传递给回调函数,该函数尚未执行.在此传递函数基本上是为服务器对象的 connection 事件添加侦听器的快捷方式.之后,我们在#5 处启动服务器.

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

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

  2. 它将 connect data end 事件侦听器添加到 stream对象(其中代表单个连接),方法是为事件挂接回调.

  3. 此后, stream 触发 connect 事件,因此执行在#2 传递的函数并写入 hello \ r \ n 到流.函数如何知道应将其写入哪个流?关闭是答案,该函数继承了它在其中创建的作用域,因此位于函数 stream 仍然引用触发我们现在处于此回调中的单个连接.

  4. 现在,客户端通过连接发送一些数据,这使得 stream 对象调用其 data 事件,因为我们在#3 我们现在将传入的数据回传给客户端.

  5. 如果客户端关闭连接,则会调用我们在#4 处绑定的函数,该函数将写入 goodbye \ r \ n ,之后从我们这边断开连接.

这会使事情变得更清楚吗?好吧,这无疑使整个事情变得容易得多.就像JavaScript在浏览器中一样,Node是单线程.在给定的时间只有一件事发生.

为简单起见,所有这些 callbacks 最终都在一个全局队列中,然后一个接一个地被调用,因此此队列可能(抽象)如下:

  |新流的连接事件|流#12的数据事件|通过setTimeout设置的回调v另一个流的关闭事件 

这些现在从上到下执行,在它们之间什么也不会发生.当您在绑定到 data 事件的 callback 中执行某项操作时,将不会发生其他事情,并且会神奇地更改系统状态.即使服务器上有一个新的传入连接,它的事件也将排队,并且必须等到它之前的所有内容(包括您当前所在的 data 事件)完成.

I'm just starting to play with Node.js today, and thought I'd start with what I thought would be a simple script: Connecting to a server via sockets, and sending a bit of data, and receiving it back. I'm creating a command line utility. Nothing in the browser.

An example of a server would be memcached, beanstalkd, etc. It seems the net module is the right tool for the job, but I'm still a bit fuzzy on the Node.js way of doing things. Some help would be appreciated.

Update #1

Let me see if I can break this down in into a couple smaller questions. I hate even asking questions like this, but the Node.js documentation is very sparse, and most documentation written 6 months ago is already out dated.

1) So I can use net.stream.write() to send data to the remote server, but I don't know how to get a response back. I'm not even sure how to test when write() is finished, because it doesn't take a callback.

2) A few clues on how the whole event.emit thing works would be great. I think that's really the key stone I'm missing in those whole thing.

Update #2

Here's where I'm still confused on implementing a client program. Let me diagram a typical send request => get response system:

1) I bind callbacks to the net module to get responses and other events, including the necessary bindings to get a response from the server.

2) I use stream.write() to send a request to the server.

3) I then do nothing, because my bound "data" event will get the response from the server.

Here's where things get tricky. Suppose I call stream.write() twice before my bound "data" event is called. Now I have a problem. When the "data" event does happen, how do I know which of the 2 requests it's a response for? Am I guaranteed that responses will take place in the same order as requests? What if responses come back in a different order?

解决方案

First of all, let's make clear what a EventEmitter is. JavaScript and therefore Node.js are asynchronous. That means, instead of having to wait for incoming connections on a server object, you add a listener to the object and pass it a callback function, which then, "as soon" as the event happens, gets executed.

There's still waiting here and there going on in the background but that has been abstracted away from you.

Let's take a look at this simple example:

// #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');

So we create the server and pass it the callback function, this function is not yet executed. Passing the function here is basically a shortcut for adding a listener for the connection event of the server object. After that we start the server at #5.

Now what happens in the case of an incoming connection?

  1. Since the function we passed to createServer was bound to the connection event, it now gets executed.

  2. It adds the connect, data and end event listeners to the stream object (which represents the individual connection) by hooking up callbacks for the events.

  3. After that, the stream fires the connect event, therefore the function passed at #2 gets executed and writes hello\r\n to the stream. How does the function know which stream it should write to? Closures are the answer, the function inherits the scope it was created in, therefore inside the function stream is still referencing to the individual connection that triggered this very callback we're in right now.

  4. Now the client sends some data over the connection, which makes the stream object call its data event, since we bound a function to this event at #3 we now echo the incoming data back to the client.

  5. In case the client closes the connection, the function we've bound at #4 gets called, which writes goodbye\r\n and after that closes the connection from our side.

Does this make things a little bit more clear? Well it definitely makes the whole thing a lot easier. Node is, just as well as JavaScript is inside Browsers, single threaded. There's only one thing happening at a given point time.

To describe it simple, all these callbacks end up in a global queue and are then called one after another, so this queue may(abstracted) look like this:

 | connection event for a new stream
 | data event for stream #12
 | callback set via setTimeout
 v close event of yet another stream

These are now get executed top to bottom, nothing will ever happen in between those. There's no chance, that while you're doing something in the callback bound to the data event, something will other will happen and magically change the state of the system. Even if there is a new incoming connection on the server, its event will get queued up and it will have to wait until everything before it, including the data event you're currently in, finishes.

这篇关于Node.js:使用套接字连接到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆