📜  门| GATE-CS-2016(Set 1)|问题9(1)

📅  最后修改于: 2023-12-03 15:28:44.630000             🧑  作者: Mango

GATE-CS-2016(Set 1) Problem 9

This problem asks you to write a program in C++ to implement a simple chat server that uses a mediator design pattern. The chat server should allow multiple clients to connect and communicate with each other through the server.

To implement this, you will need to use sockets to establish connections between the clients and the server. You will also need to use multithreading to handle multiple connections at the same time.

Here is an example implementation of the chat server:

#include <iostream>
#include <vector>
#include <thread>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

using namespace std;

class Client {
public:
    Client(int socket, sockaddr_in address) {
        this->socket = socket;
        this->address = address;
    }

    ~Client() {
        close(socket);
    }

    int getSocket() {
        return socket;
    }

    sockaddr_in getAddress() {
        return address;
    }

private:
    int socket;
    sockaddr_in address;
};

class Mediator {
public:
    void addClient(Client *client) {
        clients.push_back(client);
    }

    void removeClient(Client *client) {
        vector<Client *>::iterator it;
        it = find(clients.begin(), clients.end(), client);
        if (it != clients.end()) {
            clients.erase(it);
        }
    }

    void broadcast(string message, Client *sender) {
        vector<Client *>::iterator it;
        for (it = clients.begin(); it != clients.end(); ++it) {
            if (*it != sender) {
                send((*it)->getSocket(), message.c_str(), message.length(), 0);
            }
        }
    }

private:
    vector<Client *> clients;
};

void handleClient(Client *client, Mediator *mediator) {
    char buffer[1024] = {0};
    int valread;

    while (true) {
        valread = read(client->getSocket(), buffer, 1024);
        if (valread == 0) {
            cout << "Client disconnected" << endl;
            mediator->removeClient(client);
            break;
        }
        string message(buffer, valread);
        cout << "Received message: " << message << endl;
        mediator->broadcast(message, client);
    }

    delete client;
}

void startServer() {
    int server_socket;
    sockaddr_in address;
    const int PORT = 8888;

    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    bind(server_socket, (sockaddr*)&address, sizeof(address));
    listen(server_socket, 5);

    Mediator *mediator = new Mediator();

    while (true) {
        int new_socket;
        sockaddr_in client_address;
        int client_address_len = sizeof(client_address);

        new_socket = accept(server_socket, (sockaddr*)&client_address, (socklen_t*)&client_address_len);

        cout << "New client connected" << endl;

        Client *client = new Client(new_socket, client_address);
        mediator->addClient(client);

        thread t(handleClient, client, mediator);
        t.detach();
    }
}

int main(int argc, char const *argv[]) {
    startServer();
    return 0;
}

This implementation defines two classes: Client and Mediator. Client stores information about a connected client, including its socket and address. Mediator manages the communication between clients by keeping track of connected clients and broadcasting messages to all clients except the one that sent the message.

The main startServer() function sets up the server socket, listens for incoming connections, and spawns a new thread for each connected client.

The handleClient() function is called from each thread and handles communication with a single client. It reads incoming messages from the client, broadcasts the message to all other clients using the Mediator, and removes the client from the Mediator's list when the client disconnects.

This implementation uses raw C-style sockets and is not very robust or error-tolerant. However, it should give you a good idea of how a simple chat server using the mediator pattern can be implemented in C++.