Sockets
Overview
This section provides detailed documentation for the Windows Socket API (Winsock), a platform-independent interface for network programming on Windows. Sockets are a fundamental mechanism for inter-process communication (IPC) and network communication. They allow applications to send and receive data across a network using standard protocols like TCP and UDP.
The Winsock API provides a set of functions and structures that enable developers to create client and server applications for various network scenarios. This includes:
- Establishing reliable connections using TCP.
- Sending and receiving datagrams using UDP.
- Performing network operations asynchronously.
- Managing network configurations and addresses.
Key Concepts
Socket Types
Winsock supports different types of sockets, each suited for different communication patterns:
- Stream Sockets (
SOCK_STREAM): Provide a reliable, ordered, bidirectional, connection-oriented byte stream. Typically used with TCP. - Datagram Sockets (
SOCK_DGRAM): Provide a connectionless, unreliable datagram service. Data is sent in discrete packets. Typically used with UDP. - Raw Sockets (
SOCK_RAW): Allow direct access to IP datagrams, bypassing the transport layer. Useful for custom protocols or network diagnostics.
Address Families
Sockets are bound to specific address families, defining the network protocols they can use:
- AF_INET: IPv4 protocol family.
- AF_INET6: IPv6 protocol family.
- AF_UNSPEC: Unspecified. Allows the system to choose an appropriate address family.
Core Functions
The following are some of the most commonly used Winsock functions for socket programming:
| Function | Description |
|---|---|
socket() |
Creates a new socket. |
bind() |
Associates a local address with a socket. |
listen() |
Enables a socket to accept incoming connections. |
accept() |
Accepts an incoming connection request on a socket. |
connect() |
Establishes a connection to a remote socket. |
send() / WSASend() |
Sends data over a socket. |
recv() / WSARecv() |
Receives data from a socket. |
sendto() / WSASendTo() |
Sends data to a specific address on a datagram socket. |
recvfrom() / WSARecvFrom() |
Receives data from an address on a datagram socket. |
closesocket() |
Closes an existing socket. |
getaddrinfo() |
Resolves a network address and service. |
freeaddrinfo() |
Frees address information returned by getaddrinfo(). |
Example: TCP Client
Here's a simplified example of a TCP client establishing a connection and sending data:
#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] = {0};
int recvResult;
// Initialize Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed." << std::endl;
return 1;
}
// Create a socket
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}
// Prepare the sockaddr_in structure
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("127.0.0.1"); // Target IP address
clientService.sin_port = htons(8080); // Target port
// Connect to server
if (connect(ConnectSocket, (struct sockaddr*)&clientService, sizeof(clientService)) == SOCKET_ERROR) {
std::cerr << "connect failed: " << WSAGetLastError() << std::endl;
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Send data
const char* sendbuf = "Hello, Server!";
if (send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0) == SOCKET_ERROR) {
std::cerr << "send failed: " << WSAGetLastError() << std::endl;
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
std::cout << "Sent: " << sendbuf << std::endl;
// Receive data
recvResult = recv(ConnectSocket, buffer, sizeof(buffer) - 1, 0);
if (recvResult > 0) {
buffer[recvResult] = '\0'; // Null-terminate the received data
std::cout << "Received: " << buffer << std::endl;
} else if (recvResult == 0) {
std::cout << "Connection closed by peer." << std::endl;
} else {
std::cerr << "recv failed: " << WSAGetLastError() << std::endl;
}
// Clean up
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
WSA* variants).
Further Reading