Open In App

Two way communication between Client and Server using Win32 Threads

Last Updated : 26 Jul, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisite: Socket Programming in C/C++
It is possible to send data from the server and receive a response from the client. Similarly, the client can also send and receive data to-and-from. Here we will discuss the approach using Win32 Threads in C/C++.

Approach:

  1. Use CreateThread function which creates a new thread for a process.
  2. The CreateThread method must specify the starting address of the code that the new thread is to execute. Following is the prototype of CreateThread function:
    HANDLE CreateThread( 
      LPSECURITY_ATTRIBUTES lpThreadAttributes,
      DWORD dwStackSize, 
      LPTHREAD_START_ROUTINE lpStartAddress,
      LPVOID lpParameter, DWORD dwCreationFlags,
       LPDWORD lpThreadId 
    );
    
  3. Then using WaitForSingleObject function that returns message in form of object received from client, to receive data from client. Following is the prototype of WaitForSingleObject function:
    DWORD WaitForSingleObject(
      HANDLE hHandle,        
      DWORD dwMilliseconds
    );
    

Creating the Server program
In the Server Program, we will be using two threads, one for Sending data to the client and another for Receiving data from the client. The process of communication stops when both Client and Server type “exit“.

Below is the implementation of the Server Program:

Server




// C++ program to create Server
  
#include <iostream>
#include <string.h>
#include <winsock2.h>
using namespace std;
  
// Function that receive data
// from client
DWORD WINAPI serverReceive(LPVOID lpParam)
{
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created client socket
    SOCKET client = *(SOCKET*)lpParam;
  
    // Server executes continuously
    while (true) {
  
        // If received buffer gives
        // error then return -1
        if (recv(client, buffer, sizeof(buffer), 0)
            == SOCKET_ERROR) {
            cout << "recv function failed with error "
                 << WSAGetLastError() << endl;
            return -1;
        }
  
        // If Client exits
        if (strcmp(buffer, "exit") == 0) {
            cout << "Client Disconnected."
                 << endl;
            break;
        }
  
        // Print the message
        // given by client that
        // was stored in buffer
        cout << "Client: " << buffer << endl;
  
        // Clear buffer message
        memset(buffer, 0,
               sizeof(buffer));
    }
    return 1;
}
  
// Function that sends data to client
DWORD WINAPI serverSend(LPVOID lpParam)
{
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created client socket
    SOCKET client = *(SOCKET*)lpParam;
  
    // Server executes continuously
    while (true) {
  
        // Input message server
        // wants to send to client
        gets(buffer);
  
        // If sending failed
        // return -1
        if (send(client,
                 buffer,
                 sizeof(buffer), 0)
            == SOCKET_ERROR) {
            cout << "send failed with error "
                 << WSAGetLastError() << endl;
            return -1;
        }
  
        // If server exit
        if (strcmp(buffer, "exit") == 0) {
            cout << "Thank you for using the application"
                 << endl;
            break;
        }
    }
    return 1;
}
  
// Driver Code
int main()
{
    // Data
    WSADATA WSAData;
  
    // Created socket server
    // and client
    SOCKET server, client;
  
    // Socket address for server
    // and client
    SOCKADDR_IN serverAddr, clientAddr;
  
    WSAStartup(MAKEWORD(2, 0), &WSAData);
  
    // Making server
    server = socket(AF_INET,
                    SOCK_STREAM, 0);
  
    // If invalid socket created,
    // return -1
    if (server == INVALID_SOCKET) {
        cout << "Socket creation failed with error:"
             << WSAGetLastError() << endl;
        return -1;
    }
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(5555);
  
    // If socket error occurred,
    // return -1
    if (bind(server,
             (SOCKADDR*)&serverAddr,
             sizeof(serverAddr))
        == SOCKET_ERROR) {
        cout << "Bind function failed with error: "
             << WSAGetLastError() << endl;
        return -1;
    }
  
    // Get the request from
    // server
    if (listen(server, 0)
        == SOCKET_ERROR) {
        cout << "Listen function failed with error:"
             << WSAGetLastError() << endl;
        return -1;
    }
  
    cout << "Listening for 
            incoming connections...." << endl;
  
            // Create buffer[]
            char buffer[1024];
  
    // Initialize client address
    int clientAddrSize = sizeof(clientAddr);
  
    // If connection established
    if ((client = accept(server,
                         (SOCKADDR*)&clientAddr,
                         &clientAddrSize))
        != INVALID_SOCKET) {
        cout << "Client connected!" << endl;
        cout << "Now you can use our live chat application."
             << "Enter \"exit\" to disconnect" << endl;
  
        // Create variable of
        // type DWORD
        DWORD tid;
  
        // Create Thread t1
        HANDLE t1 = CreateThread(NULL,
                                 0,
                                 serverReceive,
                                 &client,
                                 0,
                                 &tid);
  
        // If created thread
        // is not created
        if (t1 == NULL) {
            cout << "Thread Creation Error: "
                 << WSAGetLastError() << endl;
        }
  
        // Create Thread t2
        HANDLE t2 = CreateThread(NULL,
                                 0,
                                 serverSend,
                                 &client,
                                 0,
                                 &tid);
  
        // If created thread
        // is not created
        if (t2 == NULL) {
            cout << "Thread Creation Error: "
                 << WSAGetLastError() << endl;
        }
  
        // Received Objects
        // from client
        WaitForSingleObject(t1,
                            INFINITE);
        WaitForSingleObject(t2,
                            INFINITE);
  
        // Close the socket
        closesocket(client);
  
        // If socket closing
        // failed.
        if (closesocket(server)
            == SOCKET_ERROR) {
            cout << "Close socket failed with error: "
                 << WSAGetLastError() << endl;
            return -1;
        }
        WSACleanup();
    }
}



Run the ServerApplication.cpp file using the command:

g++ ServerApplication.cpp -lws2_32 

Creating the Client Program
In the Client Program, we will be using two threads one for Sending data to the server and another for Receiving data from the server. The process of communication stops when both Server and Client type “exit“.

Client




// C++ program to create client
  
#include <iostream>
#include <string.h>
#include <winsock2.h>
using namespace std;
  
// Function that receive data from server
DWORD WINAPI clientReceive(LPVOID lpParam)
{
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created server socket
    SOCKET server = *(SOCKET*)lpParam;
  
    // Client executes continuously
    while (true) {
  
        // If received buffer gives
        // error then return -1
        if (recv(server, buffer,
                 sizeof(buffer), 0)
            == SOCKET_ERROR) {
            cout << "recv function failed with error: "
                 << WSAGetLastError()
                 << endl;
            return -1;
        }
  
        // If Server exits
        if (strcmp(buffer, "exit") == 0) {
            cout << "Server disconnected."
                 << endl;
            return 1;
        }
  
        // Print the message
        // given by server that
        // was stored in buffer
        cout << "Server: " << buffer << endl;
  
        // Clear buffer message
        memset(buffer, 0, sizeof(buffer));
    }
    return 1;
}
  
// Function that sends data to server
DWORD WINAPI clientSend(LPVOID lpParam)
{
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created server socket
    SOCKET server = *(SOCKET*)lpParam;
  
    // Client executes continuously
    while (true) {
  
        // Input message client
        // wants to send to server
        gets(buffer);
  
        // If sending failed
        // return -1
        if (send(server,
                 buffer,
                 sizeof(buffer), 0)
            == SOCKET_ERROR) {
            cout << "send failed with error: "
                 << WSAGetLastError() << endl;
            return -1;
        }
  
        // If client exit
        if (strcmp(buffer, "exit")
            == 0) {
            cout << "Thank you for using the application"
                 << endl;
            break;
        }
    }
    return 1;
}
  
// Driver Code
int main()
{
    // Input data
    WSADATA WSAData;
  
    // Created socket server
    SOCKET server;
    SOCKADDR_IN addr;
  
    WSAStartup(MAKEWORD(2, 0), &WSAData);
  
    // If invalid socket created,
    // return -1
    if ((server = socket(AF_INET,
                         SOCK_STREAM, 0))
        == INVALID_SOCKET) {
        cout << "Socket creation failed with error: "
             << WSAGetLastError() << endl;
        return -1;
    }
  
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(5555);
  
    // If connection failed
    if (connect(server,
                (SOCKADDR*)&addr,
                sizeof(addr))
        == SOCKET_ERROR) {
        cout << "Server connection failed with error: "
             << WSAGetLastError() << endl;
        return -1;
    }
  
    // If connection established
    cout << "Connected to server!"
         << endl;
    cout << "Now you can use our live chat application."
         << " Enter \"exit\" to disconnect"
         << endl;
    DWORD tid;
  
    // Create Thread t1
    HANDLE t1 = CreateThread(NULL,
                             0,
                             clientReceive,
                             &server,
                             0, &tid);
  
    // If created thread
    // is not created
    if (t1 == NULL)
        cout << "Thread creation error: "
             << GetLastError();
  
    // Create Thread t2
    HANDLE t2 = CreateThread(NULL,
                             0,
                             clientSend,
                             &server,
                             0, &tid);
  
    // If created thread
    // is not created
    if (t2 == NULL)
        cout << "Thread creation error: "
             << GetLastError();
  
    // Received Objects
    // from client
    WaitForSingleObject(t1, INFINITE);
    WaitForSingleObject(t2, INFINITE);
  
    // Socket closed
    closesocket(server);
    WSACleanup();
}


Run the ClientApplication.cpp file using the command:

g++ ClientApplication.cpp -lws2_32 

Output After communication between Server and Client

The left side command prompt is the ServerApplication and the right side command prompt is the ClientApplication.



Similar Reads

Difference Between Daemon Threads and User Threads In Java
In Java, there are two types of threads: Daemon ThreadUser Thread Daemon threads are low priority threads which always run in background and user threads are high priority threads which always run in foreground. User Thread or Non-Daemon are designed to do specific or complex task where as daemon threads are used to perform supporting tasks. Differ
4 min read
Setting up local DNS server between client-server machines
In this, article you will see the overview of DNS server and how to set up the local DNS server between the client and server machines. And here we will use Wireshark. Let's discuss it one by one. Introduction :A DNS server is computer server that contains a database of public IP addresses and their associated hostname, and in most cases serves to
5 min read
Difference between data communication and digital communication
The terms Data Communication and Digital Communication share a common word, i.e. Communication between them. Communication that natively means to share something; makes these terms look similar, but they are quite different from each other. While one term relates more to what is being communicated other is closer to what is the type and process of
7 min read
Difference between Satellite Communication and Optical Communication
Satellite Communication: In satellite communication, geostationary communication satellites are used for the purpose of communication. A satellite works as a relay station in space through which communication takes place anywhere in the world. It takes the signal from one earth station, amplifies it, enhances the quality of signals, and transmits i
3 min read
Difference between Analog Communication and Digital Communication
1. Analog Communication: In analog communication the data is transferred with the help of analog signal in between transmitter and receiver. Any type of data is transferred in analog signal. Any data is converted into electric form first and after that it is passed through communication channel. Analog communication uses a continuous signal which v
3 min read
What are the Two Broad Classes of Middleware in Client Server Environment?
Server: A server is a computer program that provides services, data, information to other computer programs. Client: A client is a host computer, requests services or information from the server. the client is also called a user. In a computer system, a client is a computer program that asks something from the server and the server gives the inform
5 min read
Java Implementation of Diffie-Hellman Algorithm between Client and Server
Program to implement Diffie-Hellman Algorithm in Client-Server Fashion. Prerequisite: Server Socket Programming, Diffie-Hellman algorithm The Diffie Hellman Algorithm is being used to establish a shared secret that can be used for secret communications while exchanging data over a public network. In the below program, the client will share the valu
4 min read
Difference between Client-Server and Peer-to-Peer Network
Client-Server Network: This model are broadly used network model. In Client-Server Network, Clients and server are differentiated, Specific server and clients are present. In Client-Server Network, Centralized server is used to store the data because its management is centralized. In Client-Server Network, Server respond the services which is reque
2 min read
Difference between Client /Server and Distributed DBMS
1. Client/Server : Client/server is developed to deal with various computing environments that have a large number of computers and servers connected together via a network. In this architecture, a Client is a user machine which provides the user interface and local processing capabilities. When any client requires additional functionality like dat
2 min read
Difference between Client side filter and Server side filters in Cyber Security
Filters are used to check whether the input entered by user is following the accepted standard or not. Filters are used either in browser (client side filtering) or in server (server side filtering) to validate the input given by the user in web application. 1. Server Side Filters : These are the types of filter checks present in the server. When t
2 min read