Microsoft Learn

TCP Client/Server (Basic) - Sample Code

This section provides the source code for a basic TCP client and server application. This sample demonstrates fundamental concepts of network communication using TCP sockets in a Windows environment.

Client Code

C#
C++
Program.cs (Client)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class TcpClientExample
{
    public static void Main(string[] args)
    {
        try
        {
            // Define server IP address and port
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            int port = 11000;
            TcpClient client = new TcpClient();

            Console.WriteLine($"Connecting to server at {ipAddress}:{port}...");
            client.Connect(ipAddress, port);
            Console.WriteLine("Connected to server.");

            // Get a stream object for reading and writing
            NetworkStream stream = client.GetStream();

            // Send message to server
            string messageToSend = "Hello from TCP Client!";
            byte[] data = Encoding.ASCII.GetBytes(messageToSend);
            stream.Write(data, 0, data.Length);
            Console.WriteLine($"Sent: {messageToSend}");

            // Receive response from server
            byte[] buffer = new byte[256];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);
            string responseData = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"Received: {responseData}");

            // Close everything
            stream.Close();
            client.Close();
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine($"ArgumentNullException: {e}");
        }
        catch (SocketException e)
        {
            Console.WriteLine($"SocketException: {e}");
        }
        finally
        {
            Console.WriteLine("Client finished.");
        }
    }
}
client.cpp
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>

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

int main()
{
    WSADATA wsaData;
    SOCKET clientSocket = INVALID_SOCKET;
    struct sockaddr_in serverAddr;
    int iResult;

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

    // Create a SOCKET for connecting to server
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
        WSACleanup();
        return 1;
    }

    // Setup the server address structure
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(11000); // Server port
    inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // Server IP address

    // Connect to server.
    iResult = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (iResult == SOCKET_ERROR) {
        std::cerr << "connect failed with error: " << WSAGetLastError() << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }

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

    // Send an initial buffer
    std::string messageToSend = "Hello from TCP Client!";
    iResult = send(clientSocket, messageToSend.c_str(), (int)messageToSend.length(), 0);
    if (iResult == SOCKET_ERROR) {
        std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }

    std::cout << "Sent: " << messageToSend << std::endl;

    char recvbuf[512];
    int recvbuflen = 512;

    // Receive until the peer closes the connection
    iResult = recv(clientSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0) {
        std::cout << "Received: " << std::string(recvbuf, 0, iResult) << std::endl;
    } else if (iResult == 0) {
        std::cout << "Connection closing..." << std::endl;
    } else {
        std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
    }

    // Cleanup
    closesocket(clientSocket);
    WSACleanup();

    std::cout << "Client finished." << std::endl;
    return 0;
}

Server Code

C#
C++
Program.cs (Server)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpServerExample
{
    private TcpListener server;
    private bool isServerRunning = true;

    public TcpServerExample(int port)
    {
        IPAddress localAddr = IPAddress.Any;
        server = new TcpListener(localAddr, port);
    }

    public void Start()
    {
        try
        {
            server.Start();
            Console.WriteLine($"Server started. Listening on port {((IPEndPoint)server.LocalEndpoint).Port}...");

            while (isServerRunning)
            {
                Console.WriteLine("Waiting for a connection...");
                TcpClient client = server.AcceptTcpClient();
                Console.WriteLine("Client connected!");

                // Handle client connection in a separate thread
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine($"SocketException: {e}");
        }
        finally
        {
            server.Stop();
            Console.WriteLine("Server stopped.");
        }
    }

    public void Stop()
    {
        isServerRunning = false;
        if (server != null)
        {
            server.Stop();
        }
    }

    private void HandleClientComm(object clientObj)
    {
        TcpClient tcpClient = (TcpClient)clientObj;
        NetworkStream stream = null;
        try
        {
            stream = tcpClient.GetStream();
            byte[] buffer = new byte[1024];
            int bytesRead;

            // Read incoming data
            bytesRead = stream.Read(buffer, 0, buffer.Length);
            string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"Received from client: {data}");

            // Send response back to client
            string responseMessage = "Message received by server!";
            byte[] responseData = Encoding.ASCII.GetBytes(responseMessage);
            stream.Write(responseData, 0, responseData.Length);
            Console.WriteLine($"Sent to client: {responseMessage}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error handling client: {e.Message}");
        }
        finally
        {
            stream?.Close();
            tcpClient?.Close();
            Console.WriteLine("Client connection closed.");
        }
    }

    public static void Main(string[] args)
    {
        int port = 11000;
        TcpServerExample server = new TcpServerExample(port);
        server.Start();
    }
}
server.cpp
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#include <vector>
#include <process.h> // For _beginthreadex

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

// Thread function for handling client connections
unsigned __stdcall ClientHandler(void* pParam)
{
    SOCKET clientSocket = (SOCKET)pParam;
    char buffer[512];
    int bytesReceived;

    std::cout << "Client connected. Waiting for data..." << std::endl;

    // Receive data from client
    bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
    if (bytesReceived > 0) {
        buffer[bytesReceived] = '\0'; // Null-terminate the received data
        std::string receivedData(buffer);
        std::cout << "Received: " << receivedData << std::endl;

        // Send response back to client
        std::string responseMessage = "Message received by server!";
        send(clientSocket, responseMessage.c_str(), (int)responseMessage.length(), 0);
        std::cout << "Sent: " << responseMessage << std::endl;
    } else if (bytesReceived == 0) {
        std::cout << "Client disconnected gracefully." << std::endl;
    } else {
        std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
    }

    // Cleanup the client socket
    closesocket(clientSocket);
    std::cout << "Client connection closed." << std::endl;
    _endthreadex(0);
    return 0;
}

int main()
{
    WSADATA wsaData;
    SOCKET listenSocket = INVALID_SOCKET;
    struct sockaddr_in serverAddr;
    int iResult;

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

    // Create a SOCKET for the server to listen on
    listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSocket == INVALID_SOCKET) {
        std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
        WSACleanup();
        return 1;
    }

    // Setup the server structure
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY; // Listen on any interface
    serverAddr.sin_port = htons(11000);      // Port to listen on

    // Bind the socket
    iResult = bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (iResult == SOCKET_ERROR) {
        std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    // Listen on the socket
    if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {
        std::cerr << "listen failed with error: " << WSAGetLastError() << std::endl;
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

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

    SOCKET clientSocket;
    while (true) {
        std::cout << "Waiting for a connection..." << std::endl;

        // Accept a client socket
        clientSocket = accept(listenSocket, NULL, NULL);
        if (clientSocket == INVALID_SOCKET) {
            std::cerr << "accept failed with error: " << WSAGetLastError() << std::endl;
            // Optionally break or continue based on error severity
            continue;
        }

        // Create a new thread to handle the client
        unsigned threadID;
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientHandler, (void*)clientSocket, 0, &threadID);
        if (hThread == 0) {
            std::cerr << "Failed to create client handling thread. Error: " << GetLastError() << std::endl;
            closesocket(clientSocket); // Close the client socket if thread creation fails
        } else {
            CloseHandle(hThread); // Close the thread handle to release resources
        }
    }

    // No explicit cleanup for listenSocket here as the loop is infinite for a typical server.
    // In a real application, you would have a mechanism to gracefully shut down the server.
    // closesocket(listenSocket);
    // WSACleanup();
    // return 0;
}