Windows Sockets API (Winsock)

The Windows Sockets API (Winsock) is a Microsoft Windows implementation of the Berkeley sockets API. It is the primary mechanism for network communication on Windows systems. Winsock provides a standard interface for applications to communicate over a network, supporting various network protocols such as TCP/IP, UDP, and others.

Note: This documentation provides a comprehensive guide to using the Windows Sockets API for developing network-aware applications on Windows. We will cover core concepts, essential functions, data structures, and best practices.

Core Concepts

Understanding the following core concepts is crucial for effective use of Winsock:

  • Sockets: An endpoint for communication. A socket is defined by an IP address and a port number.
  • Protocols: Winsock supports various transport layer protocols, primarily TCP (Transmission Control Protocol) for reliable, connection-oriented communication and UDP (User Datagram Protocol) for connectionless, unreliable datagram transmission.
  • Address Families: Specifies the network protocol family. The most common is AF_INET for IPv4 and AF_INET6 for IPv6.
  • Socket Types: Defines the semantics of communication. SOCK_STREAM is typically used with TCP, and SOCK_DGRAM with UDP.
  • Byte Order: Network byte order (big-endian) is different from host byte order on many systems. Winsock provides functions like ntohs and htons to manage this.

Key Winsock Functions

The following are some of the most fundamental Winsock functions:

  • socket(): Creates a new socket.
  • bind(): Associates a local address and port with a socket.
  • listen(): Places a socket in a listening state, ready to accept incoming connection requests.
  • accept(): Accepts an incoming connection request on a listening socket.
  • connect(): Establishes a connection to a remote host.
  • send() / sendto(): Sends data over a socket.
  • recv() / recvfrom(): Receives data from a socket.
  • closesocket(): Closes an existing socket.

Example: Basic TCP Client

Here's a simplified example of a TCP client that connects to a server, sends a message, and receives a response:


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

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

int main() {
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct sockaddr_in clientService;
    char buffer[512];
    int bytesSent, bytesRecv;

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

    // Create a socket
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    // Setup the server address
    clientService.sin_family = AF_INET;
    clientService.sin_port = htons(27015); // Example port
    inet_pton(AF_INET, "127.0.0.1", &clientService.sin_addr); // Example server IP

    // Connect to server
    if (connect(ConnectSocket, (struct sockaddr *) &clientService, sizeof(clientService)) == SOCKET_ERROR) {
        printf("connect failed with error: %ld\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Send data
    const char *sendbuf = "Hello, Server!";
    bytesSent = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (bytesSent == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
    printf("Bytes Sent: %ld\n", bytesSent);

    // Receive data
    bytesRecv = recv(ConnectSocket, buffer, 512, 0);
    if (bytesRecv == SOCKET_ERROR) {
        printf("recv failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
    printf("Bytes received: %d\n", bytesRecv);
    printf("Received: %s\n", buffer);

    // Clean up
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
                    

Further Reading