MSDN Samples: Windows Networking Echo Server

Sample Title: Echo Server

Category: Windows Networking

Description: This sample demonstrates the fundamental principles of creating a simple TCP echo server using Windows Sockets (Winsock). When a client connects, the server reads data sent by the client and echoes it back. This is a basic building block for understanding network communication.

Overview

This project provides a C++ implementation of a basic TCP echo server. It listens for incoming connections on a specified port, accepts them, and then enters a loop to receive data from the connected client and send the same data back. This allows for simple testing of network connectivity and basic socket programming.

Files

EchoServer.cpp (Excerpt)

Below is a simplified excerpt of the core logic found in EchoServer.cpp:

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

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

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

SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}

sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888); // Port to listen on
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(ListenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
closesocket(ListenSocket);
WSACleanup();
return 1;
}

if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
std::cerr << "listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(ListenSocket);
WSACleanup();
return 1;
}

std::cout << "Echo Server started. Listening on port 8888..." << std::endl;

SOCKET ClientSocket;
while (true) {
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
std::cerr << "accept failed with error: " << WSAGetLastError() << std::endl;
continue;
}

std::cout << "Client connected." << std::endl;

char buffer[4096];
int recv_size;

while ((recv_size = recv(ClientSocket, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[recv_size] = '\0'; // Null-terminate the received data
std::cout << "Received: " << buffer << std::endl;

send(ClientSocket, buffer, recv_size, 0); // Echo data back
std::cout << "Echoed back: " << buffer << std::endl;
}

if (recv_size == 0) {
std::cout << "Client disconnected." << std::endl;
} else if (recv_size == SOCKET_ERROR) {
std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
}

closesocket(ClientSocket);
}

closesocket(ListenSocket);
WSACleanup();
return 0;
}

README.md (Key Points)

The README.md file typically contains instructions for building and running the sample. Key steps usually involve:

EchoClient.cpp (Usage)

A typical echo client will perform the following actions:

  1. Initialize Winsock.
  2. Create a TCP socket.
  3. Resolve the server's address and port.
  4. Connect to the server.
  5. Send data to the server.
  6. Receive the echoed data back from the server.
  7. Close the socket and clean up Winsock.