El cliente es quien se conectará al servidor, quien enviará mensajes y recibirá mensajes de otros clientes. En principio como debe ser una sala de chat.
El cliente es quien se conectará al servidor, quien enviará mensajes y recibirá mensajes de otros clientes. En principio como debe ser una sala de chat.
Librerías:
Algunas de las librerías que estaremos utilizando seran estas: #include - Contiene las definiciones de las macros, las constantes, las declaraciones de funciones de la biblioteca estándar del lenguaje de programación C para hacer operaciones, estándar, de entrada y salida. #include - Biblioteca estándar de propósito general del lenguaje de programación C. Contiene los prototipos de funciones de C para gestión de memoria dinámica, control de procesos y otras. #include - Contiene algunas funciones y tipos y algunas operaciones de manipulación de memoria. #include - Define constantes y tipos simbólicos misceláneos, y declara funciones misceláneas. #include <sys/types.h> - Define algunos tipos adicionales. #include <sys/socket.h> - Define alguno tipos y macros para establecer una conexión con otro ordenador que nos permitirá intercambiar datos. #include <netinet/in.h> #include <arpa/inet.h> #include - Define algunas funciones y tipos para manejar procesos hijos o hilos dentro de nuestros programas. #include "commons.h" - define algunas funciones comunes que utilizaremos en el proyecto.
void emisor(); //maneja los mensajes de entrada
void receptor(); //maneja los mensajes de entrada
int main(int argc, char **argv);
Las funciones del codigo del cliente se explican por sí solas, tendremos un proceso central en el main que será el encargado de configurar y establecer inicialmente una conexión con el servidor, mientras que las otras funciones son hilos apartes encargados de manejar los mensajes entrantes y salientes.
La primera parte, la definición misma de la función y tal vez muchos iniciados en el lenguaje nunca la hayan visto, son esos dos argumentos de la función.
int main(int argc, char **argv)
Y es de saber que la función recibe dos parámetros, un número y un array de punteros a caracteres. Estos argumentos vienen desde cuando se ejecuta el programa desde una consola y se le pasan lo que llamamos argumentos del sistema.
De esta manera al ejecutar la linea “./client 8000” le estariamos mandando los siguientes datos a la función main.
argc | argv |
2 | [“./client”,”8000”] |
Una vez aclaramos esto, utilizamos esta función, para pasarle directamente el puerto de la máquina al que queremos que se conecte.
if (argc != 2)
{
printf("Uso: %s \n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]); //Convierte string a int
Se define la ip del servidor, que como estamos en la misma máquina, es la ip local y procedemos a configurar la conexión del socket.
struct sockaddr_in server_addr;
// Configuracion del Socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
Todas estas son configuraciones necesarias a la hora de conectarnos a la red ya sea local, entre varias máquinas o a la internet. Entonces estaría listo para conectarse:
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1)
{
printf("ERROR: conectando\n");
return EXIT_FAILURE;
}
Connect es una librería de socket que intenta establecer una coneccion a la dirección ip y el puerto que se le designaron, si la coneccion es fallida, devuelve un -1. Una vez exitosa la coneccion se lleva a cabo el primer mensaje al servidor, que es el nombre de usuario que se pidió anteriormente. Se crean 2 hilos para manejar tanto las comunicaciones entrantes y salientes.
send(sockfd, name, 32, 0);
printf("=== Bienvenido a la sala de chat ===\n");
pthread_t hilo_emisor; //Creacion del hilo emisor
if (pthread_create(&hilo_emisor, NULL, (void *)emisor, NULL) != 0)
{
printf("ERROR: pthread - Hilo del emisor\n");
return EXIT_FAILURE;
}
pthread_t hilo_receptor; //Creacion del hilo receptor
if (pthread_create(&hilo_receptor, NULL, (void *)receptor, NULL) != 0)
{
printf("ERROR: pthread - Hilo del receptor\n");
return EXIT_FAILURE;
}
Ya al final este proceso quedará en un bucle infinito y para desconectarse del chat será con Ctrl+C.
Una vez establecida la conexión con el servidor el hilo emisor llama a la función emisor y esperará hasta que el usuario realice una entrada en el teclado.
void emisor()
{
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while (1)
{
memset(message, 0, LENGTH); //resetea el buffer de mensajes
memset(buffer, 0, LENGTH+32); //resetea el buffer de mensajes
reset_stdout(); // Vacía el búfer de salida.
fgets(message, LENGTH, stdin); //captura el mensaje del usuario
message[strcspn(message, "\n")] = '\0'; //elimina los saltos de linea
sprintf(buffer, "%s-> %s\n", name, message);
send(sockfd, buffer, strlen(buffer), 0); //envia el mensaje all servidor
}
}
Este hilo constantemente está comprobando los mensajes recibidos por el socket desde el servidor y se encarga de imprimirlos en pantalla.
void receptor()
{
char message[LENGTH] = {};
while (1)
{
int receive = recv(sockfd, message, LENGTH, 0); //recibe los mensajes del servidor
if (receive > 0)
{
printf("%s", message); //Imprime los mensajes del servidor
reset_stdout(); // Vacía el búfer de salida.
}
else if (receive == 0)
{
break;
}
else
{
// -1
}
memset(message, 0, sizeof(message)); //resetea el buffer de mensajes
}
}
Y así cada vez que realice una nueva entrada, esté while infinito, enviará los mensajes, ya formateados con el nombre del emisor al servidor.
A continuacion en la siguiente parte del tutorial, empezaremos con el codigo del servidor.
Deja una respuesta