• No results found

2-2 Creating Connections to Your Server Problem

You need to create a connection to a networked server.

Solution

In order to build a connection to your server, you need to know the port or UNIX path on which is it listening. Once you know this, you can create a connection via Node.js. For this you will once again use the Node.js native net module, which exposes a createConnection method for connecting to a remote (or local) instance.

To utilize the net module to connect to a server via Node.js, you, once again, must set the connection to the net module via a CommonJS require as shown in Listing 2-6.

Listing 2-6. Importing the net Module for Connections var net = require('net');

Then the next step is to call the createConnection method passing in the port or UNIX path on which to connect. Optionally, you can also pass the host if you need to specify an IP address. Now we can create a connectListener that logs the connection to the console, as shown in Listing 2-7.

Listing 2-7. Creating a Connection to Your Server var net = require('net');

// createConnection

var connection = net.createConnection({port: 8181, host:'127.0.0.1'}, // connectListener callback

function() {

console.log('connection successful'); });

Chapter 2 ■ NetworkiNg with Node.js

How It Works

In this section you created a connection to a TCP server. This was done with Node.js’s net module. This contained the createConnection function, which is the same as the connect() function. The connect method first checks the arguments that you passed to it. It will evaluate which options are set.

Checking the arguments sent is done by first checking if the first argument is an object, then subsequently parsing that object if it is indeed an object. If the first argument is not an object, it is evaluated to see if it is a valid pipe name, in which case it will be set as the UNIX path option. If it is not the name of a pipe, it will default to a port number. The final check of the parameters is for the optional callback argument, which is evaluated by checking to see if the last parameter passed to the connect() function is a function itself. This whole process is run in a function called normalizeConnectArgs, shown in Listing 2-8.

Listing 2-8. Extracting createConnection Arguments function normalizeConnectArgs(args) {

var options = {};

if (typeof args[0] === 'object') { // connect(options, [cb]) options = args[0]; } else if (isPipeName(args[0])) { // connect(path, [cb]); options.path = args[0]; } else { // connect(port, [host], [cb]) options.port = args[0];

if (typeof args[1] === 'string') { options.host = args[1];

} }

var cb = args[args.length - 1];

return (typeof cb === 'function') ? [options, cb] : [options]; }

Next, the net module creates a new socket object, passing in the newly normalized connect arguments. This socket has a method on its prototype called connect.

This connect method on the socket is called, passing to it the normalized arguments as well. The connect method will try to create a new socket handle and connect to the path or port and host combination that was specified in the arguments. If the host is not specified for a given port, then it is assumed that the host being targeted is the localhost, or 127.0.0.1. Where this gets interesting is that, if a hostname or IP address is provided in the arguments, Node.js will require the dns module and perform a DNS lookup to locate the host. This again will default to the localhost if the lookup returns null without an error, as shown in Listing 2-9.

Listing 2-9. Socket.prototype.connect’s Method to Resolve Path, Port, and Host /* ... */

if (pipe) {

connect(self, options.path);

} else if (!options.host) { debug('connect: missing host');

Chapter 2 ■ NetworkiNg with Node.js

} else {

var host = options.host;

debug('connect: find host ' + host);

require('dns').lookup(host, function(err, ip, addressType) { // It's possible we were destroyed while looking this up.

// XXX it would be great if we could cancel the promise returned by // the lookup.

if (!self._connecting) return; if (err) {

// net.createConnection() creates a net.Socket object and // immediately calls net.Socket.connect() on it (that's us). // There are no event listeners registered yet so defer the // error event to the next tick.

process.nextTick(function() { self.emit('error', err); self._destroy(); }); } else { timers.active(self); addressType = addressType || 4;

// node_net.cc handles null host names graciously but user land // expects remoteAddress to have a meaningful value

ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); connect(self, ip, options.port, addressType, options.localAddress); }

}); } /* ... */

As can be seen in the listing, the result of discovering the path, port, or port and host is to call the function connect(). This function simply connects the socket handle to the path or port and host. Once the connection request has connected, the connectListener callback is called as the code for the connect function shown in Listing 2-10. Listing 2-10. function connect( ) Implementation in the net Module

function connect(self, address, port, addressType, localAddress) { assert.ok(self._connecting); if (localAddress) { var r; if (addressType == 6) { r = self._handle.bind6(localAddress); } else { r = self._handle.bind(localAddress); }

Chapter 2 ■ NetworkiNg with Node.js self._destroy(errnoException(process._errno, 'bind')); return; } } var connectReq; if (addressType == 6) {

connectReq = self._handle.connect6(address, port); } else if (addressType == 4) {

connectReq = self._handle.connect(address, port); } else {

connectReq = self._handle.connect(address, afterConnect); } if (connectReq !== null) { connectReq.oncomplete = afterConnect; } else { self._destroy(errnoException(process._errno, 'connect')); } }

This was the function in Listing 2-8 where you logged “connection successful” to the console. As you will see in Section 2-4 there is much more to listening and connecting a client than simply logging a string to the console, but first you will examine the various ways in which to configure your server and the default settings that accompany the configuration options.

2-3. Configuring Server Defaults