The Startup
Published in

The Startup

Closing TCP/UDP Sockets With Timeouts and Error Handling in Nodejs

I’m not a big fan of the built-in `dgram` and `net` libraries in Nodejs, but it’s really easy to create sockets and write networking applications with Nodejs. One of the biggest issues I’m constantly seeing is the lack of cleanup functionalities when using the socket libraries in Nodejs.

This code is from our DNS npm package that we use in Violetnorth

You can find the Violetnorth — DNS npm package here: github.com/violetnorth/dns

So I’m going to talk about a quick way to clean up sockets with timeouts and overall error handling when dealing with sockets.

If you don’t implement some sort of timeout, you are going to run out of available sockets especially when using TCP sockets.

Sockets usually hang and there needs to be timeout handling to close the socket if it’s hanging, which is not super apparent with Nodejs.

Here is an example function that uses a TCP socket to do a DNS lookup.

// TCP socket with timeoutconst dns = require("dns");
const net = require("net");
const dnsPacket = require("dns-packet");

const resolveTCP = (packet, addr, port = 53, timeout) => {
return new Promise((resolve, reject) => {
const socket = new net.Socket();

const id = setTimeout(() => {
clearTimeout(id);
socket.destroy();
reject("timed out");
return;
}, parseInt(timeout));

socket.connect(parseInt(port), addr, () => {
socket.write(packet);
});

let message = Buffer.alloc(4096);
socket.on("data", data => {
message = Buffer.concat([message, data], message.length + data.length);
});

socket.on("drain", () => {
clearTimeout(id); // Clear the timeout if you are going to close the socket manually.
socket.destroy();
resolve(dnsPacket.decode(message));
return;
});

socket.on("end", () => {
clearTimeout(id); // Clear the timeout if you are going to close the socket manually.
socket.destroy();
resolve(dnsPacket.decode(message));
return;
});

socket.on("error", err => {
reject(err);
return;
});

socket.on("close", function() {
resolve(dnsPacket.decode(message));
return;
});
});
};

Another example function that uses a UDP socket to do a DNS lookup.

// UDP socket with timeoutconst dns = require("dns");
const dgram = require("dgram");
const dnsPacket = require("dns-packet");

const _resolveUDP = (packet, addr, port = 53, timeout) => {
return new Promise((resolve, reject) => {
const socket = dgram.createSocket("udp4");

const id = setTimeout(() => {
clearTimeout(id);
socket.close();
reject("timed out");
return;
}, parseInt(timeout));

socket.on("message", message => {
clearTimeout(id); // Clear the timeout if you are going to close the socket manually.
socket.close();
resolve(dnsPacket.decode(message));
return;
});

socket.on("error", err => {
clearTimeout(id); // Clear the timeout if you are going to close the socket manually.
socket.close();
reject(err);
return;
});

socket.send(packet, 0, packet.length, parseInt(port), addr, err => {
if (err) {
clearTimeout(id); // Clear the timeout if you are going to close the socket manually.
socket.close();
reject(err);
}
});
});
};

The idea is basically to create a named timeout function which will close the socket after the specified timeout milliseconds, but you have to clear the timeout function every time you close the socket manually (in the case of an error for example).

Otherwise, you will see unhandled errors due to trying to close an already closed socket.

Anyways, that’s pretty much it, error handling and timeouts with Nodejs sockets.

--

--

--

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +756K followers.

Recommended from Medium

Understanding “This” in javascript through interview questions

Getting Started with DOM Manipulation in JavaScript

Coding Bootcamp Week 3/13: More JavaScript Fundamentals + Recursions and Object-Oriented…

Laravel 8 Export Data to Excel and PDF using DataTables

Angular Directive to adjust your component height as per window inner height

Angular Directive to adjust your component height as per window inner height

Understanding Axure RP 10 New Features

WTF!? Creating your first React App (Part 2/5)

JavaScript Function Construction (Part 5)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Koray Göçmen

Koray Göçmen

University of Toronto, Computer Engineering, architected and implemented reliable infrastructures and worked as the lead developer for multiple startups.

More from Medium

What is NodeJS? Part-1

Beginners guide to NodeJs

Collaborative Drawing App: Using the Database

What is Node.Js?