wsapoll

The wsapoll function checks a specified set of sockets for readiness to perform I/O operations.

Syntax
int wsapoll(
  _Inout_  SOCKET_FD *fdarray,
  _In_     unsigned long nfds,
  _In_opt_ const struct timeval *timeout
);

Parameters

Parameter Description
fdarray

A pointer to an array of SOCKET_FD structures. Each structure contains a socket descriptor and flags indicating the events to monitor.

The SOCKET_FD structure is defined as:

typedef struct _SOCKET_FD {
    SOCKET s;
    int events;
    int revents;
} SOCKET_FD, *PSOCKET_FD;
  • s: The socket descriptor.
  • events: A bitmask indicating the requested events. Supported events include:
    • POLLIN: Data is available for reading.
    • POLLPRI: Urgent data is available for reading.
    • POLLOUT: Data can be written to the socket.
    • POLLERR: An error occurred on the socket.
    • POLLHUP: Hang-up occurred on the socket.
    • POLLRDNORM: Normal data is available for reading.
    • POLLWRNORM: Normal data can be written to the socket.
    • POLLRDBAND: Priority data is available for reading.
    • POLLWRBAND: Priority data can be written to the socket.
  • revents: A bitmask indicating the events that actually occurred on the socket. This member is set by the wsapoll function.
nfds The number of elements in the fdarray array.
timeout

An optional pointer to a timeval structure that specifies the time interval, in milliseconds, to wait for an event. The structure is defined as:

struct timeval {
    long tv_sec;    /* Seconds */
    long tv_usec;   /* Microseconds */
};
  • If timeout is NULL, wsapoll blocks indefinitely until an event occurs.
  • If timeout points to a structure with both tv_sec and tv_usec set to 0, wsapoll returns immediately without blocking.

Return Value

If the call is successful, wsapoll returns the number of SOCKET_FD structures in the fdarray array for which the revents member is non-zero. This indicates that an event occurred on these sockets.

If timeout expires before any events occur, wsapoll returns 0.

If an error occurs, wsapoll returns -1, and the global variable WSAGetLastError can be called to retrieve the specific error code.

Remarks

The wsapoll function provides a portable way to monitor multiple sockets for I/O readiness. It is a POSIX-compliant function adapted for Windows Sockets.

When wsapoll returns, you should iterate through the fdarray. For each structure where revents is non-zero, you can check the specific bits set in revents to determine which event(s) occurred and then take appropriate action.

Note: Ensure that the events member is set correctly for each socket before calling wsapoll. The revents member is initialized to zero by the caller and is set by the function.

The POLLERR and POLLHUP events are special. If these events are set in revents, it indicates a problem with the socket, and you should typically close the socket.

This function is available starting with Windows Vista and Windows Server 2008.

Example

The following code snippet demonstrates how to use wsapoll to check for readability on two sockets.

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

#define MAX_SOCKETS 2
#define TIMEOUT_MS 5000 // 5 seconds

int main() {
    WSADATA wsaData;
    SOCKET sock1, sock2;
    SOCKET_FD fd_array[MAX_SOCKETS];
    struct timeval timeout;
    int ret;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("WSAStartup failed.\n");
        return 1;
    }

    // Create dummy sockets for demonstration (replace with actual socket creation)
    sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    sock2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (sock1 == INVALID_SOCKET || sock2 == INVALID_SOCKET) {
        printf("Socket creation failed.\n");
        WSACleanup();
        return 1;
    }

    // Configure the sockets for polling
    fd_array[0].s = sock1;
    fd_array[0].events = POLLIN; // Check for readability
    fd_array[0].revents = 0;

    fd_array[1].s = sock2;
    fd_array[1].events = POLLIN; // Check for readability
    fd_array[1].revents = 0;

    // Set the timeout
    timeout.tv_sec = TIMEOUT_MS / 1000;
    timeout.tv_usec = (TIMEOUT_MS % 1000) * 1000;

    printf("Polling for socket readiness for %d seconds...\n", TIMEOUT_MS / 1000);

    ret = wsapoll(fd_array, MAX_SOCKETS, &timeout);

    if (ret == SOCKET_ERROR) {
        printf("wsapoll failed with error: %d\n", WSAGetLastError());
    } else if (ret == 0) {
        printf("Timeout occurred: No sockets are ready.\n");
    } else {
        printf("Found %d ready sockets.\n", ret);
        for (int i = 0; i < MAX_SOCKETS; i++) {
            if (fd_array[i].revents & POLLIN) {
                printf("Socket %d is ready for reading.\n", fd_array[i].s);
                // Perform read operation here...
            }
            if (fd_array[i].revents & POLLERR) {
                printf("An error occurred on socket %d.\n", fd_array[i].s);
            }
             if (fd_array[i].revents & POLLHUP) {
                printf("Hang-up occurred on socket %d.\n", fd_array[i].s);
            }
        }
    }

    closesocket(sock1);
    closesocket(sock2);
    WSACleanup();

    return 0;
}

Requirements

Client: Windows Vista and later

Server: Windows Server 2008 and later

Header: Winsock2.h

Library: Ws2_32.lib

DLL: Ws2_32.dll