我正在使用Fedora作为操作系统在C上开发一个聊天室(基于客户机/服务器体系结构)套接字应用程序。我在这两个过程之间的通信遇到了麻烦。
代码如下:
服务器
#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);
线程保持打开状态,但从不接收来自客户端的消息。
我一直在网上寻找示例作为指导,但我无法使用。
谢谢。