To create a TCP server on a TouchBerry Pi Panel PC or a Raspberry PLC, install a current LTS version of Node.js and use its built-in net module. net.createServer() handles each client that connects, and listen(5566) opens the port on every network interface of the device. The example in this post is an echo server: it replies with the same data it receives.
The server is the other end of the Node.js TCP client of the same series. It works with that client, with an Arduino PLC as client or with any tool that opens a TCP connection.
The first version of this post used a TouchBerry Pi 3, now discontinued, and Node.js 6. The steps are the same on the current TouchBerry Pi Panel PC and on any Raspberry PLC, because both run Raspberry Pi OS (Debian).
- Step 1Install Node.jsCurrent LTS version from NodeSource
- Step 2Write server.jsBuilt-in net module, no packages
- Step 3Test itOn the device, then from the client
- Step 4Start it at bootA systemd service
The network of the example
| Device | Role | Address |
|---|---|---|
| TouchBerry Pi or Raspberry PLC | TCP server | 192.168.1.30, port 5566 |
| TouchBerry Pi, Raspberry PLC, PC or Arduino PLC | TCP client | 192.168.1.25 |
A server needs an address that does not change, or the clients will not find it after a reboot. Give it a static IP address first, with nmcli on Bookworm and Trixie or with dhcpcd.conf on older systems. The steps are in how to set a static IP address on a TouchBerry Pi or Raspberry PLC.
Both devices must be in the same subnet, or have a route between them. Check it with ip a and ip route.
Step 1: install Node.js LTS
First check if Node.js is already installed:
node -v
A Raspberry PLC prepared with the Industrial Shields image or install.sh script already has Node.js, because the script installs Node-RED with it. If node -v shows version 22 or later, go to step 2.
If Node.js is missing or older, do not install the nodejs package of Debian: Bookworm has Node.js 18, which reached its end of life in April 2025. Install the LTS version with the setup script of NodeSource:
sudo apt update
sudo apt install -y curl
curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt install -y nodejs
node -v
This replaces the setup_6.x script of the first version of this post. Node.js 6 has been out of support since 2019, and that script no longer installs a supported version.
Step 2: write the TCP server
Create a folder for the project and open a new file:
mkdir -p ~/tcp-server
cd ~/tcp-server
nano server.js
Paste this code. The comments explain each part:
#!/usr/bin/env node
// TCP server: accepts several clients and replies with the same data (echo)
const net = require('node:net');
const PORT = Number(process.argv[2]) || 5566; // TCP port to listen on
const HOST = '0.0.0.0'; // all IPv4 addresses of the device: eth0, eth1, wlan0
const server = net.createServer((socket) => {
const who = `${socket.remoteAddress}:${socket.remotePort}`;
console.log('Client connected: ' + who);
socket.on('data', (data) => {
console.log(`Received from ${who}: ${data.toString().trim()}`);
socket.write(data); // reply with the same data
});
socket.on('error', (err) => console.error(`Error with ${who}: ${err.message}`));
socket.on('close', () => console.log('Client disconnected: ' + who));
});
server.on('error', (err) => {
console.error('Server error: ' + err.message); // for example EADDRINUSE
process.exit(1);
});
server.listen(PORT, HOST, () => {
console.log(`TCP server listening on ${HOST}:${PORT}`);
});
How it works:
net.createServer()runs the function once for each client that connects. Several clients can be connected at the same time.listen(PORT, '0.0.0.0')opens the port on all the IPv4 addresses of the device, so the clients can use the address ofeth0,eth1or the Wi-Fi.- The
dataevent receives what the client sends, andsocket.write()sends it back. - The
errorevent of the server stops the program with exit code 1 if the port cannot be opened, for example when another program uses it.
The port comes from the command line, so node server.js 6000 listens on port 6000. Without an argument it uses 5566, like the client of part 2. Save with Ctrl+O and exit with Ctrl+X.
Step 3: test the server
Start the server:
node server.js
In a second terminal on the same device, connect with nc (netcat) and type a line. The server sends the same line back. Close nc with Ctrl+C. If nc is missing, install it with sudo apt install netcat-openbsd.
nc 127.0.0.1 5566
Then test from the other device with the client of part 2, with the address of the server:
node client.js 192.168.1.30 5566
The client prints the reply:
Connected to 192.168.1.30:5566
Received: Hello from the TCP client
Connection closed
And the server shows who connected and what it received:
TCP server listening on 0.0.0.0:5566
Client connected: 192.168.1.25:50412
Received from 192.168.1.25:50412: Hello from the TCP client
Client disconnected: 192.168.1.25:50412
If the client cannot connect, check the server side first:
| Symptom | Likely cause | What to do |
|---|---|---|
EADDRINUSE when the server starts | Another program, or another copy of the server, uses the port | Stop it, or start the server with another port |
EACCES when the server starts | Ports below 1024 need root permissions | Use a port from 1024 up, like 5566 |
The client gets ECONNREFUSED | Nothing listens on that address and port | Check with ss -ltnp | grep 5566 that the server listens |
| The client gets a timeout | Wrong address, no route or a firewall in between | Check ip a on the server and ping 192.168.1.30 from the client |
Step 4: start the server when the device boots
On a machine, the server must start on its own after a power cut. A systemd service does it. First check where node is:
which node
With the NodeSource packages, the answer is /usr/bin/node. Create the service file:
sudo nano /etc/systemd/system/tcp-server.service
Paste this content. Change the user pi and the folder if yours are different:
[Unit]
Description=TCP echo server with Node.js
After=network-online.target
Wants=network-online.target
[Service]
User=pi
WorkingDirectory=/home/pi/tcp-server
ExecStart=/usr/bin/node /home/pi/tcp-server/server.js 5566
Restart=on-failure
[Install]
WantedBy=multi-user.target
Enable and start the service, check its state and follow its messages:
sudo systemctl daemon-reload
sudo systemctl enable --now tcp-server
systemctl status tcp-server
journalctl -u tcp-server -f
Restart=on-failure starts the server again if it stops with an error. Leave the log with Ctrl+C: the service keeps running.
FAQ about TCP servers with Node.js
Do I need to install a package with npm?
No. The net module is part of Node.js, so this server does not need npm install.
Can several clients connect at the same time?
Yes. Node.js calls the function of createServer() for each connection, and each client has its own socket. The test of this post connected three clients at once.
How do I read complete messages?
TCP sends a stream of bytes, not messages. One data event can bring half a message or two messages. If your clients end each message with \n, keep the data in a buffer and process it line by line.
Which Node.js version should I use?
A version in LTS (long-term support), which receives security updates for about 30 months. Up to Node.js 26 only even-numbered versions become LTS; from Node.js 27 every major version does. Check node -v from time to time.
TCP with Industrial Shields devices
- Set a static IP address on a TouchBerry Pi or Raspberry PLC
- TCP client with Node.js
- TCP client on an Arduino PLC, if the client is an M-Duino
- TCP server on an Arduino PLC
The TouchBerry Pi Panel PC (7", 10.1" and 18.5") and the Raspberry PLC run Linux, so the same Node.js server works on both.
Take it further
A TCP connection is how a panel or a Linux PLC talks to the rest of the line. These pages use it in real projects.
PLC Solution Library
TCP socket between Python and Node-RED on a Raspberry PLC
A Python control process and a Node-RED dashboard exchange encoder data and start, stop and exit commands over TCP.
See the example
Case study
Water bottling with a TouchBerry Pi Panel PC
A TouchBerry Pi 7" runs a water bottling station as PLC and HMI: conveyor, sensors, cylinder and pump on its own I/O.
Read the case study