Microsoft Developer Network

Introduction to Winsock Programming

Winsock (Windows Sockets API) is the networking API for Windows. It provides a standard interface for applications to access network services. This guide covers the fundamental concepts and common practices for developing network applications using Winsock.

Key Concepts

Winsock provides a set of functions and structures that allow developers to create network-aware applications. These include:

  • Sockets: Endpoints for communication.
  • Protocols: Such as TCP (Transmission Control Protocol) for reliable, ordered delivery and UDP (User Datagram Protocol) for faster, less reliable communication.
  • Address Families: For example, AF_INET for IPv4 and AF_INET6 for IPv6.
  • Data Transfer: Functions for sending and receiving data.

Getting Started

To begin Winsock programming, you need to initialize the Winsock DLL. This is typically done using the `WSAStartup` function.

int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);

The `WSAStartup` function loads the Winsock DLL and makes it available for use. It's crucial to call `WSACleanup` when your application is finished with Winsock.

Socket Creation

Sockets are created using the `socket` function:

SOCKET socket(int af, int type, int protocol);

Here, `af` specifies the address family (e.g., `AF_INET`), `type` specifies the socket type (e.g., `SOCK_STREAM` for TCP or `SOCK_DGRAM` for UDP), and `protocol` specifies the protocol (usually 0 to let the system choose based on type).

Connecting and Listening (TCP)

For TCP connections, a server typically calls `bind` to associate a socket with a specific local address and port, then `listen` to mark it as a passive socket ready to accept incoming connections. A client uses `connect` to establish a connection to a remote server.

Example: Simple Echo Client

Below is a simplified C++ snippet demonstrating a basic Winsock client that connects to a server and echoes data.

// Include necessary headers
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment(lib, "Ws2_32.lib")

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

    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed." << std::endl;
        return 1;
    }

    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        std::cerr << "Error at socket(): %ld\n" << WSAGetLastError() << std::endl;
        WSACleanup();
        return 1;
    }

    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1"); // Connect to localhost
    clientService.sin_port = htons( 27015 );

    if (connect( ConnectSocket, (struct sockaddr*) &clientService, sizeof(clientService)) == SOCKET_ERROR) {
        std::cerr << "connect failed." << std::endl;
        WSACleanup();
        return 1;
    }

    std::cout << "Connected to server." << std::endl;

    const char* sendbuf = "Hello, Server!";
    bytesSent = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );

    if (bytesSent == SOCKET_ERROR) {
        std::cerr << "send failed." << std::endl;
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    bytesRecv = recv(ConnectSocket, buffer, 512 - 1, 0);
    if (bytesRecv == SOCKET_ERROR) {
        std::cerr << "recv failed." << std::endl;
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
    else if (bytesRecv == 0) {
        std::cout << "Connection closed." << std::endl;
    } else {
        buffer[bytesRecv] = '\0';
        std::cout << "Received: " << buffer << std::endl;
    }

    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}

Further Reading