Skip to main content

VxWorks select() Guide: Build a Multi-Client TCP Server

·760 words·4 mins
VxWorks RTOS Networking Sockets Select() Multi-Client Embedded Systems Programming
Table of Contents

VxWorks select() Guide: Build a Multi-Client TCP Server

🚀 Introduction
#

In the previous tutorial, you built a basic TCP client/server. But real systems rarely talk to just one client.

So how do you handle multiple simultaneous connections without spawning a task per client?

The answer is select().

This guide shows how to build a multi-client TCP server in VxWorks using a single task, keeping resource usage low while maintaining responsiveness.


🧩 What is select()?
#

select() is a system call that allows you to monitor multiple sockets at once and determine which ones are ready for I/O.

Instead of blocking on a single socket, your task can:

  • Wait for new connections
  • Receive data from multiple clients
  • React only when something actually happens

Function Prototype
#

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

Key Idea
#

You give select() a set of file descriptors, and it tells you:

  • Which sockets are ready to read
  • Which are ready to write
  • Which have errors

This is the foundation of event-driven networking in embedded systems.


⚙️ Why Use select() in VxWorks?
#

In resource-constrained environments, this matters a lot.

Without select()
#

  • One task per client
  • High memory usage
  • Context-switch overhead

With select()
#

  • Single task handles all clients
  • Lower memory footprint
  • Deterministic behavior

This makes it ideal for RTOS-based systems like VxWorks.


💻 Example: Multi-Client TCP Echo Server
#

This example demonstrates a server that:

  • Listens on port 6000
  • Accepts multiple clients
  • Echoes received data back to each client

Code Example
#

#include <vxWorks.h>
#include <taskLib.h>
#include <sockLib.h>
#include <inetLib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define SERVER_PORT 6000
#define MAX_CLIENTS 5

void multiClientServerTask()
{
    int serverSock, clientSock, maxFd, activity, i;
    int clientSockets[MAX_CLIENTS];
    struct sockaddr_in serverAddr, clientAddr;
    fd_set readFds;
    char buffer[256];
    int addrLen = sizeof(clientAddr);

    // Initialize client sockets
    for (i = 0; i < MAX_CLIENTS; i++)
        clientSockets[i] = 0;

    // Create server socket
    serverSock = socket(AF_INET, SOCK_STREAM, 0);

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(SERVER_PORT);

    bind(serverSock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    listen(serverSock, 3);

    printf("Server listening on port %d\n", SERVER_PORT);

    while (1)
    {
        FD_ZERO(&readFds);
        FD_SET(serverSock, &readFds);
        maxFd = serverSock;

        // Add client sockets
        for (i = 0; i < MAX_CLIENTS; i++)
        {
            if (clientSockets[i] > 0)
                FD_SET(clientSockets[i], &readFds);

            if (clientSockets[i] > maxFd)
                maxFd = clientSockets[i];
        }

        // Wait for activity
        activity = select(maxFd + 1, &readFds, NULL, NULL, NULL);

        // New connection
        if (FD_ISSET(serverSock, &readFds))
        {
            clientSock = accept(serverSock,
                                (struct sockaddr*)&clientAddr,
                                &addrLen);

            printf("New client connected (fd=%d)\n", clientSock);

            for (i = 0; i < MAX_CLIENTS; i++)
            {
                if (clientSockets[i] == 0)
                {
                    clientSockets[i] = clientSock;
                    break;
                }
            }
        }

        // Handle client data
        for (i = 0; i < MAX_CLIENTS; i++)
        {
            int sd = clientSockets[i];

            if (FD_ISSET(sd, &readFds))
            {
                int bytes = recv(sd, buffer, sizeof(buffer) - 1, 0);

                if (bytes <= 0)
                {
                    printf("Client disconnected (fd=%d)\n", sd);
                    close(sd);
                    clientSockets[i] = 0;
                }
                else
                {
                    buffer[bytes] = '\0';
                    printf("Client %d: %s\n", sd, buffer);

                    send(sd, buffer, bytes, 0);
                }
            }
        }
    }
}

void usrAppInit(void)
{
    taskSpawn("tMultiServer", 100, 0, 8000,
              (FUNCPTR)multiClientServerTask,
              0,0,0,0,0,0,0,0,0,0);
}

📝 Code Walkthrough
#

1. Server Setup
#

  • Create socket using socket()
  • Bind to port 6000
  • Start listening with listen()

2. File Descriptor Management
#

Each loop iteration:

  • Clear the set with FD_ZERO

  • Add:

    • Server socket → for new connections
    • Client sockets → for incoming data

3. Waiting for Events
#

select(maxFd + 1, &readFds, NULL, NULL, NULL);

This blocks until:

  • A new client connects
  • A client sends data

4. Accepting Clients
#

If the server socket is ready:

clientSock = accept(...)
  • Add the new socket to the clientSockets[] array
  • Track it for future reads

5. Handling Client Data
#

For each client:

  • If data is received → process it
  • If connection closed → clean up

⚡ Example Output
#

Server listening on port 6000
New client connected (fd=4)
Client 4: Hello
New client connected (fd=5)
Client 5: Hi Server
Client 4: How are you?

🔍 Key Takeaways
#

  • select() enables event-driven networking in VxWorks
  • One task can efficiently handle multiple clients
  • Ideal for embedded systems with limited resources
  • Avoids overhead of thread-per-connection models

⚠️ Practical Tips
#

  • Always track maxFd correctly
  • Use timeouts if you need periodic processing
  • Avoid large MAX_CLIENTS unless necessary
  • For high scalability, consider poll() or advanced mechanisms (if available)

✅ Wrap-Up
#

You’ve now learned how to:

  • Use select() in VxWorks
  • Build a multi-client TCP server
  • Efficiently manage multiple sockets in a single task

This pattern is widely used in embedded networking and forms the basis of more advanced designs.

Reference: VxWorks select() Guide: Build a Multi-Client TCP Server

Related

VxWorks Programming Guide: Hello World for Beginners
·518 words·3 mins
VxWorks RTOS Embedded Systems Programming Tutorial
VxWorks Shell Editing and Object Module Loader Guide
·589 words·3 mins
VxWorks Kernel Shell RTOS Embedded Systems Command Line Object Module Loader VI Editor Emacs Mode
VxWorks in Aerospace and Defense: Powering Missions Beyond Earth
·756 words·4 mins
VxWorks RTOS Aerospace Defense Embedded Systems