🚀 Introduction #
In the previous blog Networking with VxWorks: Socket Programming Basics, we wrote a simple TCP server and client.
But what if you need to handle multiple clients at the same time?
Instead of spawning one task per client (which may waste resources), you can use the select() system call to handle multiple sockets in a single task.
In this tutorial, you’ll learn:
- What
select()does in VxWorks. - How to monitor multiple sockets for incoming data.
- How to build a multi-client TCP server.
🧩 What is select()?
#
select()is a system call that monitors multiple file descriptors (sockets) at once.- It tells you which sockets are ready for reading, writing, or errors.
- Useful for servers handling many clients simultaneously.
Prototype in VxWorks (same as BSD):
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
💻 Example: Multi-Client TCP Server with select()
#
We’ll build a server that:
- Listens on port 6000.
- Accepts multiple clients.
- Echoes back any messages received.
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 array
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("Multi-Client Server: Listening on port %d\n", SERVER_PORT);
while (1)
{
// Clear and set file descriptors
FD_ZERO(&readFds);
FD_SET(serverSock, &readFds);
maxFd = serverSock;
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);
if (FD_ISSET(serverSock, &readFds))
{
// New client connection
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;
}
}
}
// Check each client for incoming 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("Received from client %d: %s\n", sd, buffer);
// Echo back
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);
}
📝 Explanation of the Code #
-
Server Socket
- Created with
socket(), bound to port 6000, and set to listen.
- Created with
-
select()
- Monitors both the server socket (for new clients) and existing client sockets (for incoming data).
-
Accepting New Clients
- When the server socket is ready,
accept()is called to add a new client.
- When the server socket is ready,
-
Handling Client Data
- Loop through all clients and check which ones have data.
- If disconnected, close and free the slot.
- Otherwise, echo back the received message.
⚡ What You’ll See #
When multiple clients connect and send data, the output looks like:
Multi-Client Server: Listening on port 6000
New client connected (fd=4)
Received from client 4: Hello
New client connected (fd=5)
Received from client 5: Hi Server
Received from client 4: How are you?
🔍 Key Takeaways #
select()lets you manage multiple sockets in one task.- Efficient for embedded systems with limited resources.
- Useful for TCP servers handling many clients.
✅ Wrap-Up #
In this tutorial, you learned:
- How to use
select()in VxWorks. - How to manage multiple clients in a single server task.
- How to build an echo server that handles concurrent connections.
In the next blog, we’ll explore UDP programming in VxWorks, which is great for fast, connectionless communication.
👉 Stay tuned for Blog 9: “UDP Networking in VxWorks: Sending and Receiving Packets.”