es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

cómo escribir un servidor TCP multiusuario en C++ utilizando la llamada al sistema fork en sockets

Estoy escribiendo un servidor y un cliente en sockets en c++. Tengo un servidor funcionando para un solo cliente. Dime cómo usar fork para escribir un servidor multiusuario.

servidor:

int main() {
    int server_socket = Socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in adr = {0};
    adr.sin_family = AF_INET;
    adr.sin_port = htons(1110);

    Bind(server_socket, (struct sockaddr* )&adr, sizeof(adr));
    Listen(server_socket, SOMAXCONN);
    socklen_t adr_len = sizeof(adr);
    int res_accept = Accept(server_socket, (struct sockaddr* ) &adr, &adr_len);
    while(true) {
        char buffer[1024];
        ssize_t count_read = Recv(res_accept, buffer, 1024, 0);
        printf("%s\n", buffer);
        fflush(stdin);

        char res[10];
        int result = words_counter(buffer);
        sprintf(res, "%d\n", result);
        ssize_t count_send = Send(res_accept, res, 10, 0);
    }
    close(res_accept);
    close(server_socket);
    return 0;
}

cliente:

int main(int argc, char const *argv[]) {
    int client_socket = Socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in adr = {0};
    adr.sin_family = AF_INET;
    adr.sin_port = htons(1110);

    Inet_pton(AF_INET, "127.0.0.1", &adr.sin_addr);

    int res_connect = Connect(client_socket, (struct sockaddr* ) &adr, sizeof(adr));

    while (true) {

        char message[1024];

        printf("ingresa el mensaje\n");

        fgets(message, 1024, stdin);

        if (strncmp(message, "quit!", 5) == 0) break;

        ssize_t count_send = Send(client_socket, message, 1024, 0);

        char buffer[10];

        ssize_t count_read = Recv(client_socket, buffer, 10, 0);

        printf("SERVIDOR: La cantidad de palabras en el mensaje transmitido es: %s", buffer);

    }

    close(client_socket);
    return 0;
}

Utilizo funciones auxiliares escritas por mí (para un manejo de errores conveniente), como bind, listen, etc. Por lo tanto, los nombres de las funciones están escritos con letra mayúscula. Gracias por la ayuda.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para escribir un servidor multiusuario utilizando fork, puedes modificar el código server para crear un proceso hijo utilizando fork cada vez que un nuevo cliente se conecta.

    Aquí hay un ejemplo de código para el server modificado:

        int main() {
            int server_socket = Socket(AF_INET, SOCK_STREAM, 0);
    
            struct sockaddr_in adr = {0};
            adr.sin_family = AF_INET;
            adr.sin_port = htons(1110);
    
            Bind(server_socket, (struct sockaddr* )&adr, sizeof(adr));
            Listen(server_socket, SOMAXCONN);
    
            while(true) {
                socklen_t adr_len = sizeof(adr);
                int res_accept = Accept(server_socket, (struct sockaddr* ) &adr, &adr_len);
    
                pid_t pid = fork();
                if (pid == 0) {
                    // proceso hijo
                    close(server_socket);
                    handle_client(res_accept);
                    close(res_accept);
                    exit(0);
                } else if (pid > 0) {
                    // proceso padre
                    close(res_accept);
                } else {
                    perror("fork");
                }
            }
    
            close(server_socket);
            return 0;
        }
    

    En este código, cuando un nuevo cliente se conecta, el proceso principal crea un proceso hijo. El proceso hijo llama a una función separada handle_client para manejar la comunicación con el cliente, mientras que el proceso padre cierra el socket res_accept y vuelve a escuchar a nuevos clientes.

    Aquí hay una implementación de ejemplo de una función handle_client:

        void handle_client(int socket) {
            while(true) {
                char buffer[1024];
                ssize_t count_read = Recv(socket, buffer, 1024, 0);
                printf("%s\n", buffer);
                fflush(stdin);
    
                char res[10];
                int result = words_counter(buffer);
                sprintf(res, "%d\n", result);
                ssize_t count_send = Send(socket, res, 10, 0);
    
                if (count_read < 0 || count_send < 0) {
                    perror("error de comunicación");
                    break;
                }
            }
        }
    

    Esta función es similar al bucle while original en el código del servidor, pero maneja la comunicación con un cliente específico y finaliza cuando ocurre un error o el cliente se desconecta.

    Ten en cuenta que esta es solo una implementación de ejemplo y es posible que desees agregar manejo de errores y otras características según sea necesario.

Comments are closed.