Comunicación bidireccional entre el cliente y el servidor mediante subprocesos Win32

Prerrequisito: Programación de sockets en C/C++
Es posible enviar datos desde el servidor y recibir una respuesta del cliente. Del mismo modo, el cliente también puede enviar y recibir datos hacia y desde. Aquí discutiremos el enfoque usando Win32 Threads en C/C++.

Acercarse:

  1. Use la función CreateThread que crea un nuevo hilo para un proceso.
  2. El método CreateThread debe especificar la dirección de inicio del código que debe ejecutar el nuevo hilo. El siguiente es el prototipo de la función CreateThread:
    HANDLE CreateThread( 
      LPSECURITY_ATTRIBUTES lpThreadAttributes,
      DWORD dwStackSize, 
      LPTHREAD_START_ROUTINE lpStartAddress,
      LPVOID lpParameter, DWORD dwCreationFlags,
       LPDWORD lpThreadId 
    );
    
  3. Luego, use la función WaitForSingleObject que devuelve el mensaje en forma de objeto recibido del cliente, para recibir datos del cliente. El siguiente es el prototipo de la función WaitForSingleObject:
    DWORD WaitForSingleObject(
      HANDLE hHandle,        
      DWORD dwMilliseconds
    );
    

Creación del programa del servidor
En el programa del servidor, usaremos dos subprocesos, uno para enviar datos al cliente y otro para recibir datos del cliente. El proceso de comunicación se detiene cuando tanto el Cliente como el Servidor escriben « salir «.

A continuación se muestra la implementación del Programa Servidor:

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();
    }
}

Ejecute el archivo ServerApplication.cpp con el comando:

g++ ServerApplication.cpp -lws2_32 

Creación del programa cliente
En el programa cliente, usaremos dos subprocesos, uno para enviar datos al servidor y otro para recibir datos del servidor. El proceso de comunicación se detiene cuando tanto el servidor como el cliente escriben « salir «.

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();
}

Ejecute el archivo ClientApplication.cpp con el comando:

g++ ClientApplication.cpp -lws2_32 

Salida después de la comunicación entre el servidor y el cliente El símbolo del sistema del lado izquierdo es ServerApplication y el símbolo del sistema del lado derecho es ClientApplication .

Publicación traducida automáticamente

Artículo escrito por gvishalsai y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *