WRITING A C++ SERVER AND CLIENT SOCKET

 

Setting Up the Server

Step 1: Initialize Winsock

In the server, the first step is to initialize the Winsock library. This involves loading the DLL and setting up the necessary variables. The following code demonstrates how to achieve this:

#include <iostream>
#include <winsock2.h>
int main() {
    // Initialize WSA variables
    WSADATA wsaData;
    int wsaerr;
    WORD wVersionRequested = MAKEWORD(2, 2);
    wsaerr = WSAStartup(wVersionRequested, &wsaData);
    // Check for initialization success
    if (wsaerr != 0) {
        std::cout << "The Winsock dll not found!" << std::endl;
        return 0;
    } else {
        std::cout << "The Winsock dll found" << std::endl;
        std::cout << "The status: " << wsaData.szSystemStatus << std::endl;
    }
        
    return 0;
}

Step 2: Create a Socket

Next, we create a socket to handle communication. The socket() function is used for this purpose. It allows us to specify the address family, socket type, and protocol. In our case, we are creating a TCP socket:

// Create a socket
SOCKET serverSocket;
serverSocket = INVALID_SOCKET;
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Check for socket creation success
if (serverSocket == INVALID_SOCKET) {
    std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
    WSACleanup();
    return 0;
} else {
    std::cout << "Socket is OK!" << std::endl;
}

Step 3: Bind the Socket

Now, we bind the socket to a specific IP address and port number. This is crucial for the server to listen for incoming connections:

// Bind the socket to an IP address and port number
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");  // Replace with your desired IP address
service.sin_port = htons(55555);  // Choose a port number
// Use the bind function
if (bind(serverSocket, reinterpret_cast<SOCKADDR*>(&service), sizeof(service)) == SOCKET_ERROR) {
    std::cout << "bind() failed: " << WSAGetLastError() << std::endl;
    closesocket(serverSocket);
    WSACleanup();
    return 0;
} else {
    std::cout << "bind() is OK!" << std::endl;
}

Step 4: Listen for Connections

Now, we make the server listen for incoming connections using the listen() function:

// Listen for incoming connections
if (listen(serverSocket, 1) == SOCKET_ERROR) {
    std::cout << "listen(): Error listening on socket: " << WSAGetLastError() << std::endl;
} else {
    std::cout << "listen() is OK! I'm waiting for new connections..." << std::endl;
}

Step 5: Accept Connections

When a client attempts to connect, the server uses the accept() function to accept the incoming connection:

// Accept incoming connections
SOCKET acceptSocket;
acceptSocket = accept(serverSocket, nullptr, nullptr);
// Check for successful connection
if (acceptSocket == INVALID_SOCKET) {
    std::cout << "accept failed: " << WSAGetLastError() << std::endl;
    WSACleanup();
    return -1;
} else {
    std::cout << "accept() is OK!" << std::endl;
}

Step 6: Receive and Send Data

Now that the server is set up and connected to a client, it can send and receive data. The following code demonstrates receiving data and sending a response:

// Receive data from the client
char receiveBuffer[200];
int rbyteCount = recv(acceptSocket, receiveBuffer, 200, 0);
if (rbyteCount < 0) {
    std::cout << "Server recv error: " << WSAGetLastError() << std::endl;
    return 0;
} else {
    std::cout << "Received data: " << receiveBuffer << std::endl;
}
// Send a response to the client
char buffer[200];
std::cout << "Enter the message: ";
std::cin.getline(buffer, 200);
int sbyteCount = send(acceptSocket, buffer, 200, 0);
if (sbyteCount == SOCKET_ERROR) {
    std::cout << "Server send error: " << WSAGetLastError() << std::endl;
    return -1;
} else {
    std::cout << "Server: Sent " << sbyteCount << " bytes" << std::endl;
}

Creating the Client

Now that we have our server code, let’s set up a simple client to connect to the server and exchange messages.

Step 1: Initialize Winsock and Create a Socket

This step is similar to what we did in the server. Initialize Winsock and create a socket:

#include <iostream>
#include <winsock2.h>
int main() {
    // Initialize WSA variables
    WSADATA wsaData;
    int wserr;
    WORD wVersionRequested = MAKEWORD(2, 2);
    wserr = WSAStartup(wVersionRequested, &wsaData);
    // Check for initialization success
    if (wsaerr != 0) {
        std::cout << "The winsock dll not found" << std::endl;
        return 0;
    } else {
        std::cout << "The Winsock dll found" << std::endl;
        std::cout << "The status: " << wsaData.szSystemStatus << std::endl;
    }
    // Create a socket
    SOCKET clientSocket;
    clientSocket = INVALID_SOCKET;
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // Check for socket creation success
    if (clientSocket == INVALID_SOCKET) {
        std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
        WSACleanup();
        return 0;
    } else {
        std::cout << "Socket is OK!" << std::endl;
    }
    // Continue with the client setup...
    // (See the full code here: https://github.com/Tharun8951/cpp-tcp-server/")
    return 0;
}

Step 2: Connect to the Server

Connect the client to the server using the connect() function:

// Connect to the server
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("127.0.0.1");  // Replace with the server's IP address
clientService.sin_port = htons(55555);  // Use the same port as the server
// Use the connect function
if (connect(clientSocket, reinterpret_cast<SOCKADDR*>(&clientService), sizeof(clientService)) == SOCKET_ERROR) {
    std::cout << "Client: connect() - Failed to connect: " << WSAGetLastError() << std::endl;
    WSACleanup();
    return 0;
} else {
    std::cout << "Client: Connect() is OK!" << std::endl;
    std::cout << "Client: Can start sending and receiving data..." << std::endl;
}

Step 3: Send and Receive Data

Similar to the server, the client can now send and receive data:

// Sending data to the server
char buffer[200];
std::cout << "Enter the message: ";
std::cin.getline(buffer, 200);
int sbyteCount = send(clientSocket, buffer, 200, 0);
if (sbyteCount == SOCKET_ERROR) {
    std::cout << "Client send error: " << WSAGetLastError() << std::endl;
    return -1;
} else {
    std::cout << "Client: Sent " << sbyteCount << " bytes" << std::endl;
}
// Receiving data from the server
char receiveBuffer[200];
int rbyteCount = recv(clientSocket, receiveBuffer, 200, 0);
if (rbyteCount < 0) {
    std::cout << "Client recv error: " << WSAGetLastError() << std::endl;
    return 0;
} else {
    std::cout << "Client: Received data: " << receiveBuffer << std::endl;
}
// Continue with the client setup...


Comments

Check out our works

WINDOWS SYSTEM PROGRAMMING WITH C/C++

PYTHON PROGRAMMING IN AND OUT

Creating a Reverse Shell in Python

Network programming in python with examples