Creando el cliente
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 <stdio.h> – 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 <stdlib.h> – 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 <string.h> – Contiene algunas funciones y tipos y algunas operaciones de manipulación de memoria.
#include <unistd.h> – 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 <pthread.h> – 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.
Funciones:
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.
Función main
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 conexión a la dirección ip y el puerto que se le designaron, si la conexión es fallida, devuelve un -1. Una vez exitosa la conexión 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.
Función Emisor
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 } }
Función Receptor
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 continuación en la siguiente parte del tutorial, empezaremos con el código del servidor.