Networking and Sockets

Some Definitions

Before we start, we should probably get a few definitions out of the way!

  • ip address - number given to a computer / device on a network
  • port - a number given to a communication end point that usually represents some specific service… allowing multiple services to be run on the same device… an analogy from this guide to network programming compares an ip address to a street address of a building, and a port to an apartment number in that building
  • socket - an endpoint to a connection… so there are two sockets per connection, but in network programming apis, a socket object is typically the object that mediates communication (reads/writes) to a connected client or server… this SO article goes deep on sockets vs ports
  • localhost - 127.0.0.1 … or your local computer… when used as the domain name in nc, your browser, etc. … the connection is made from your computer to a service running on itself

net module

Node comes with a built in net module. It provides functions for creating servers and clients.

The following creates a server that listens on port 8080. It will log out the address and port that connected to it.

(Details in following slide)

import net from 'net';
const HOST = '127.0.0.1';
const PORT = 8080;

const server = net.createServer((sock) => {
    console.log(`got connection from ${sock.remoteAddress}:${sock.remotePort}`);
});

server.listen(PORT, HOST);
 

Running the Above Example

To run the above example, you'll have to have two terminal windows / tabs open.

  1. run node myFile.js in one window
    • this is your server, it's waiting for connections
    • note that it'll look like terminal is frozen or waiting for something
    • anything you console.log out will be shown in this window
    • to stop your server, use CTRL + c
  2. in another terminal, use netcat as a client to connect to your server
    • nc localhost 8080
    • you can type text that gets sent to the server…
    • again, CTRL + c will close the client

createServer

The createServer function:

  1. can be called with one argument, a callback function specifying what to when a client connects
    • the callback has an argument, the "socket" that represents a "connection" to the client
    • (though again, a socket conceptually is just an end point)
  2. returns an instance of a Server object
    • this object can be bound to a port and address
    • … so that it can start listening for client connections
 

Server Object and Listen

Again, the server object has a listen method →

  • this tells the server to start accepting connections on the supplied port and hostname
  • 127.0.0.1 is localhost
  • if hostname is left out, it'll accept connections on any address (for example, binding to the current address of the machine that it's running on so that it's accessible outside of localhost)
  • leaving out the port number lets the os decide what the port number should be

Socket Object Events

You can specify what your server will do based on specific events by using the socket object that's passed in to your anonymous function / callback for initial connection.

Some examples of socket events include:

  • data - generated when socket receives data
  • close - generated when socket is closed


Use someSocketObject.on(eventName, callback) to specify what to do on these events.

On Data and On Close

Here's an example of logging out when a socket receives data… and when a socket is closed:

// setup above
const server = net.createServer((sock) => {

    sock.on('data', (binaryData) => {
        console.log(`got data\n=====\n${binaryData}`);
    });

    sock.on('close', (data) => {
        console.log(`closed - ${sock.remoteAddress}:${sock.remotePort}`);
    });
});

// listen below

 

Socket On….

Let's take a closer look at one of these event handlers:

sock.on('data', function(data) {
});


The callback function for sock.on has a single parameter, data, which represents the binary data sent to the server.

  • data is (usually) going to be a Buffer object
  • Buffer is just a representation of binary data (perhaps it's in this format because no encoding was specified!)
  • you can call toString on a Buffer object which assumes utf-8
  • you can create a buffer from a string using Buffer.from("some string", encoding), where encoding can be:
    • 'utf8'
    • 'ascii'

Write and End

Of course, you can also send data to the client with socket's write and end methods

  1. write(data, encoding) - sends data back to the connected client
    • you can send back binary data (a buffer)
    • or a string (which, by default uses utf-8 for encoding… otherwise specify by explicitly passing encoding)
  2. end - let's the client know that it wants to stop the connection
    • end also takes a single argument… which is just data to send just before closing (like calling write then end consecutively)


Example usage demonstrating a few writes, and then an end:

sock.write('hello'); 
sock.write('how are you?'); 
sock.end('goodbye');  // lets client know connection will be closed 
// (there's also sock.destroy to close the connection immediately)
 

Echo

Here's a server that just sends back the data that it is sent to it by the client. To have it disconnect after it gets data, uncomment sock.end().

// within create server
sock.on('data', function(binaryData) {
    console.log('got data\n=====\n' + binaryData); 
    sock.write(binaryData);

    // uncomment me if you want the connection to close
    // immediately after we send back data
    // sock.end();
});
 

 

posted @ 2023-02-13 06:35  M1stF0rest  阅读(13)  评论(0编辑  收藏  举报