@unrealsoftware/node_udp
v1.0.5
Published
A basic node.js module supporting binary communication via plain UDP with useful read/write methods. Light-weight & no dependencies!
Downloads
3
Maintainers
Readme
@unrealsoftware/node_udp
A basic & lightweight Node.JS module supporting binary communication via plain UDP with useful read/write methods.
Available via NPM: https://www.npmjs.com/package/@unrealsoftware/node_udp
What this module is good for?
It's a wrapper around the Node.js core module "dgram" and provides some simple read/write methods so you don't have to mess with byte buffers directly. You can use it to quickly get a UDP server up and running with very little code. Also it has no depedencies to any third party modules.
Currently comes with read/write methods for the following data types:
readByte
/writeByte
UInt8 / byte / unsigned int (1 byte) with value range 0 to 255readShort
/writeShort
UInt16 / ushort / unsigned int (2 bytes) with value range 0 to 65,535readInt
/writeInt
Int32 / int / signed int (4 bytes) with value range -2,147,483,648 to 2,147,483,647readLong
/writeLong
Int64 / long / signed int (8 bytes) with value range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807readFloat
/writeFloat
Float / float / single precision floating-point (4 bytes)readDouble
/writeDouble
Double / double / double precision floating-point (8 bytes)readSString
/writeSString
short ANSI ASCII string with up to 255 chars, length encoded with byte prefix (1 byte + 1 byte per char)readString
/writeString
ANSI ASCII string with up to 65,535 chars, length encoded with ushort prefix (2 bytes + 1 byte per char)
:information_source: All numbers are read/written with little endian (LE) byte order by default. This can be changed with a parameter in the NodeUdp constructor.
:heavy_check_mark: The module also provides automatic recovery. It closes and re-binds the socket if any error occurs. This feature can be disabled.
Limitations
We are talking about plain binary UDP here. Low level networking. No extra protocol on top. This means it comes with the typical UDP features/limitations:
- Unreliable: Messages can get lost. No acknowledgement or re-send mechanism.
- No guaranteed order: Messages can arrive in any order (or not at all).
- Message size limitation: The size of messages is limited by the MTU - which depends on used hard- and software. Keeping the payload size below ~1200 bytes should work fine in most cases. Bigger messages might not arrive.
- Unencrypted: UDP has no built-in encryption.
You can work around most of these problems by building your own protocol on top of UDP (which can be quite challenging depending on your requirements). Encryption can be added by encrypting data before sending it and decrypting it after receiving it.
:warning: Do not send private data via UDP - unless you encrypted beforehand!
The current version of NodeUdp has a few limitations on its own:
- Few data types: Only a few popular data types are supported. More types (mostly unsigned ones) could be added easily.
- ANSI ASCII only: The string methods are for sending ANSI ASCII strings only. UTF-8 or other encodings could be added easily though.
Sample
Here's a server which receives messages, reads the first byte and sends it back:
// import the module
const NodeUdp = require('@unrealsoftware/node_udp');
// create a server listening on port 54321
const udp = new NodeUdp(onResponse, 54321);
// handle incoming messages
function onResponse(data, length, addr, port) {
console.log(`Received msg from ${addr}:${port} with length ${length}`);
if (length > 0) {
const byte = data.readByte()
console.log(`First byte is ${byte}`);
// send response
udp.startResponse();
udp.outStream.writeByte(byte);
udp.sendResponse();
}
}
Constructor
The NodeUdp
constructor has 5 parameters:
const udp = new NodeUdp(onResponse, startPort = -1, rebindOnError = true, rebindDelay = 3000, littleEndian = true)
onResponse
: The response callback. Mandatory. See "Reading Messages" for details.startPort
(optional): The port the UDP socket will be bound to on construction. If you don't provide a port you have to bind the socket manually usingudp.bindSocket(port)
.rebindOnError
(optional): Try to bind the socket again after an error? This defaults to true. Set to false if you don't want the socket to be bound automatically.rebindDelay
(optional): Delay (in milliseconds) after which the program will attempt to bind the socket again after an error occurred. Defaults to 3000 ms (3 milliseconds). Not relevant ifrebindOnError
is false.littleEndian
(optional): Sets read/write methods to little endian (true, default) or big endian (false).
Receiving Messages
Messages are read in the response callback you specify as the first parameter in the constructor of NodeUdp
. It has these parameters:
data
(StreamBuffer): The data you received. You can use the read-methods mentioned above to read this data. Before reading you can usedata.avail()
to check if enough bytes are left for reading. Alternatively you can usedata.canRead()
which returns true if at least one readable byte is left.length
(number): The length (in bytes) of data. You can also usedata.length()
to retrieve this value.addr
(string): The address of the sender of the message.udp.srcAddrees
will have the same value.port
(number): The port of the sender of the message.udp.srcPort
will have the same value.
:information_source: Data in a message always has to be read in the same order it was written.
Sending Messages
Sending a message happens in 3 steps:
udp.startResponse()
resets the contents ofudp.outStream
. By default new responses will have a maximum size of 1024 bytes. For bigger responses you can provide a size e.g.udp.startResponse(2048)
. You can skip this call if you want to send the same data to multiple addresses.- Writing data. This is done via
udp.outStream.writeX
with writeX being one of the write methods mentioned above. e.g.udp.outStream.writeString('Hello, world!')
. You can write as much data as you want this way. The maximum size is however limited by the buffer size and the MTU. udp.sendResponse()
sends the data to the address and port of the last sender. Alternatively you can useudp.sendResponseTo(addr, port)
to send the message to a custom address and port.
:warning: Sending messages will fail with an error message if the socket is not bound. You can check this with udp.isBound
.
MIT License
Do with this whatever you want. No limitations. Please keep the copyright notice though. See LICENSE for details.
Made with :green_heart: in :anchor: Hamburg, Germany