C Sockets Chatroom (клиент / сервер) застрял на чтение / запись - PullRequest
0 голосов
/ 09 июля 2019

Я разрабатываю приложение сокетов для чата (на основе архитектуры клиент / сервер) на C, используя Fedora в качестве моей ОС.У меня возникли проблемы со связью между этими двумя процессами.

Вот код:

Сервер

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <pthread.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <uuid/uuid.h>
#include "definiciones.h"

//tSala salas [MAX_SALAS];

void *ConnectionHandler(void *);

int main(int argc, char const *argv[]) 
{ 
    int serverSocketFD, clientSocketFD; 
    struct sockaddr_in serverSocketAddress, clientSocketAddress; 
    int serverAddressLength, clientAddressLength;
    tUsuario *usuario;

    int cantidadMaximaUsuarios = MAX_SALAS * MAX_USUARIOS_SALA;
    int socketOption = TRUE;

    // Creación y configuración del socket
    serverSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocketFD < 0)
    { 
        perror("Server - ERROR - Hubo un error en la creacion del socket. Finalizando el sistema...\n"); 
        exit(EXIT_FAILURE); 
    } 

    // Ignore pipe signals 
    //signal(SIGPIPE, SIG_IGN);

    if (setsockopt(serverSocketFD, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, (char*)&socketOption, sizeof(socketOption))) 
    { 
        perror("Server - ERROR - Hubo un error en el seteo de las opciones del socket. Finalizando el sistema...\n");  
        exit(EXIT_FAILURE); 
    }

    serverAddressLength = sizeof(serverSocketAddress);
    clientAddressLength = sizeof(clientSocketAddress);
    memset(&serverSocketAddress, 0, serverAddressLength);
    memset(&clientSocketAddress, 0, clientAddressLength);
    serverSocketAddress.sin_family = AF_INET; 
    serverSocketAddress.sin_addr.s_addr = INADDR_ANY; 
    serverSocketAddress.sin_port = htons(PUERTO_SERVIDOR); 

    printf("Server - INFO - Configuración Inicial | Tipo de IP: IPv4 | IP: localhost | Puerto: %d\n", PUERTO_SERVIDOR);
    puts("Server - INFO - Socket creado con éxito");

    // Bindeando socket al puerto definido
    if (bind(serverSocketFD, (struct sockaddr *) &serverSocketAddress, serverAddressLength) < 0) 
    { 
        perror("Server - ERROR - Hubo un error al intentar bindear el socket al puerto. Finalizando el sistema...\n"); 
        close(serverSocketFD);
        exit(EXIT_FAILURE); 
    } 
    puts("Server - INFO - Socket bindeado con éxito");

    //Escuchando solicitudes de conexión
    if(listen(serverSocketFD, cantidadMaximaUsuarios) < 0)
    {
        perror("Server - ERROR - Hubo un error escuchando solicitudes de conexion. Finalizando el sistema...\n");
        close(serverSocketFD);
        exit(EXIT_FAILURE); 
    }
    puts("Server - INFO - Escuchando conexiones...");

    //getsockname(serverSocketFD, (struct sockaddr*) &serverSocketAddress, (socklen_t*) &serverAddressLength);
    //printf("Server - INFO - Configuración Inicial | Tipo de IP: IPv4 | IP: %s | Puerto: %d\n", inet_ntoa(serverSocketAddress.sin_addr), ntohs(serverSocketAddress.sin_port));

    while(1)
    {
        clientSocketFD = accept(serverSocketFD, (struct sockaddr *) &clientSocketAddress, (socklen_t*) &clientAddressLength);

        //getpeername(clientSocketFD, (struct sockaddr*) &clientSocketAddress, (socklen_t*) &clientAddressLength);
        //printf("Servidor - INFO - Ingreso de nuevo usuario desde %s:%d\n", inet_ntoa(clientSocketAddress.sin_addr), ntohs(clientSocketAddress.sin_port));

        pthread_t id;
        usuario = (tUsuario*) malloc(sizeof(tUsuario));
        usuario->socket = clientSocketFD; 
        //strcpy(usuario->ip, inet_ntoa(clientSocketAddress.sin_addr));

        if(pthread_create(&id, NULL, ConnectionHandler, usuario) < 0)
        {
            perror("Server - ERROR - Hubo un error intentando crear el thread del nuevo usuario\n");
        }
    } 

    return 0; 
}

void *ConnectionHandler(void *usuario)
{
    tUsuario *datosUsuario = (tUsuario*) usuario;
    int socketUsuario = datosUsuario->socket;
    int read_size;
    char nombreUsuario[MAX_NOMBRE_USUARIO] = {};
    uuid_t binuuid;
    char *uuid = malloc(37);
    char salaSeleccionada[2] = "-1";
    int* salaRandom;
    char *mensajeServidor, mensajeCliente[2000];
    int indice = 0;
    char *mensajeSalas = "Seleccione alguna de las salas disponibles: \n";
    int result;

    //printf("Socket del usuario: %d", socketUsuario);
    puts("Servidor - INFO - Thread - Hola!");
    //if (recv(socketUsuario, nombreUsuario, MAX_NOMBRE_USUARIO, 0) <= 0 /*|| validarNombreUsuario(nombreUsuario) == 0*/) 
    //{
        //uuid_generate_random(binuuid);
        //uuid_unparse_lower(binuuid, uuid);
        //sprintf(nombreUsuario, "usuario-%s", uuid);
        //puts("Server - INFO - Socket bindeado con éxito");
    //}
    result = recv( socketUsuario, nombreUsuario, MAX_NOMBRE_USUARIO, 0); 
    printf("Servidor - INFO - Thread - Nombre de usuario: %s", nombreUsuario);

    //sprintf(mensajeSalas, "Seleccione alguna de las salas disponibles: \n");
    /*for(indice; indice < MAX_SALAS; indice++)
    {
        sprintf(mensajeSalas + strlen(mensajeSalas), "Sala %d\n", indice+1);
    }
    write(socketUsuario, mensajeSalas, strlen(mensajeSalas));*/

    /*if (recv(socketUsuario, salaSeleccionada, 2, 0) <= 0 || (atoi(salaSeleccionada) < 1 || atoi(salaSeleccionada) < MAX_SALAS)) 
    {
        salaRandom = generarRandom(0, MAX_SALAS, 1);
        //puts("Server - INFO - Socket bindeado con éxito");
    } */

    //strcpy(datosUsuario->name, nombreUsuario);

    //TODO: Usar mutex para agregar un usuario a la sala

    /*else {
        strncpy(np->name, nickname, LENGTH_NAME);
        printf("%s(%s)(%d) join the chatroom.\n", np->name, np->ip, np->data);
        sprintf(send_buffer, "%s(%s) join the chatroom.", np->name, np->ip);
        send_to_all_clients(np, send_buffer);
    }*/

    //mensajeServidor = "Greetings! I am your connection handler\n";
    //write(socketUsuario, mensajeServidor, strlen(mensajeServidor));

    //mensajeServidor = "Now type something and i shall repeat what you type \n";
    //write(socketUsuario, mensajeServidor , strlen(mensajeServidor));

    /*//Receive a message from client
    while((read_size = recv(socketCliente, mensajeCliente, 2000, 0)) > 0)
    {
        mensajeCliente[read_size] = '\0';
        write(socketCliente, mensajeCliente, strlen(mensajeCliente));
        memset(mensajeCliente, 0, 2000);
    }*/

    /*if(read_size == 0)
    {
        puts("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        perror("recv failed");
    }*/

    pthread_exit ((void *)"Listo");
} 

Клиент

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "definiciones.h"
#include "funciones.h"

int main()
{
    int clientSocketFD; 
    struct sockaddr_in clientSocketAddress, serverSocketAddress; 
    int clientAddressLength, serverAddressLength;
    char username[MAX_NOMBRE_USUARIO] = {};
    char username2[MAX_NOMBRE_USUARIO] = "hola";
    char sala[2] = {};
    size_t textLength;
    char message[1000];
    char buffer[1024];

    printf("Ingrese su nombre de usuario (entre 1 y 50 caracteres): ");
    do 
    {
        fgets(username, MAX_NOMBRE_USUARIO, stdin);
        str_trim_lf(username, MAX_NOMBRE_USUARIO);
    } while (username[0] == '\0' || strlen(username) < 1 || strlen(username) > MAX_NOMBRE_USUARIO - 1);

    printf("Cliente - INFO - Su nombre de usuario es: %c%s%c\n", '/"', username, '/"');

    // Creación y configuración del socket
    clientSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    printf("Cliente - INFO - Datos del socket: %d\n", clientSocketFD);

    if (clientSocketFD < 0)
    { 
        perror("Cliente - ERROR - Hubo un error en la creacion del socket. Finalizando el sistema...\n"); 
        exit(EXIT_FAILURE); 
    } 
    puts("Cliente - INFO - Socket creado con éxito");

    serverAddressLength = sizeof(serverSocketAddress);
    clientAddressLength = sizeof(clientSocketAddress);
    memset(&serverSocketAddress, 0, serverAddressLength);
    memset(&clientSocketAddress, 0, clientAddressLength);
    serverSocketAddress.sin_family = AF_INET; 
    serverSocketAddress.sin_addr.s_addr = INADDR_ANY; 
    serverSocketAddress.sin_port = htons(PUERTO_SERVIDOR); 

    if (connect(clientSocketFD, (struct sockaddr *) &serverSocketAddress, serverAddressLength) < 0)
    {
        perror("Cliente - ERROR - Hubo un error intentando conectarse al servidor. Finalizando el sistema...\n"); 
        close(clientSocketFD);
        exit(EXIT_FAILURE); 
    }

    // Names
    getsockname(clientSocketFD, (struct sockaddr*) &clientSocketAddress, (socklen_t*) &clientAddressLength);
    getpeername(clientSocketFD, (struct sockaddr*) &serverSocketAddress, (socklen_t*) &serverAddressLength);
    printf("Cliente - INFO - Conectado al servidor: %s:%d\n", inet_ntoa(serverSocketAddress.sin_addr), ntohs(serverSocketAddress.sin_port));
    printf("Cliente - INFO - Datos de conexion: %s:%d\n", inet_ntoa(clientSocketAddress.sin_addr), ntohs(clientSocketAddress.sin_port));

    while(1)
    {
        //strcpy(username2, username);
        send(clientSocketFD, username, MAX_NOMBRE_USUARIO, 0);
        puts("Usuario enviado!");

        if(recv(clientSocketFD, buffer, 1024, 0) < 0)
        {
           perror("Cliente - ERROR - Hubo un error intentando leer los mensajes del servidor. Finalizando el sistema...\n");
        }
        printf("Cliente - INFO - Mensaje recibido del servidor: %s\n", buffer);

        fgets(sala, 2, stdin);
        str_trim_lf(sala, 2);

        /*printf("Mensaje a enviar: \n");
        scanf("%s", &message);*/

        /*if((read_size = recv(clientSocketFD, mensajeCliente, 2000, 0)) > 0)
        {
            mensajeCliente[read_size] = '\0';
            write(socketCliente, mensajeCliente, strlen(mensajeCliente));
            memset(mensajeCliente, 0, 2000);
        }*/

        if(recv(clientSocketFD, buffer, 1024, 0) < 0)
        {
           perror("Cliente - ERROR - Hubo un error intentando leer los mensajes del servidor. Finalizando el sistema...\n");
        }
        printf("Cliente - INFO - Mensaje recibido del servidor: %s\n", buffer);
    }

    close(clientSocketFD);
}

Проблема именно в коде сервера: когда он создает поток для обработки нескольких клиентских подключений, он ожидает ввода имени пользователя, введенного входящим пользователем.Это всегда застревает здесь:

result = recv( socketUsuario, nombreUsuario, MAX_NOMBRE_USUARIO, 0);

Поток остается открытым, но он никогда не получает сообщение от клиента.

Я искал в Интернете примеры для использования в качестве руководства,но я не буду работать.

Заранее спасибо.

...