↓ Skip to main content

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

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