Servidor UDP en Linux:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
char buffer[BUFFER_SIZE];
struct sockaddr_in: Es una estructura para manejar direcciones IPv4 en sockets. server_addr: Almacena la dirección IP y el puerto del servidor. Se configura para indicar dónde se reciben los datos. client_addr: Almacena la dirección IP y el puerto del cliente. Se usa para identificar quién envió los datos (en el servidor UDP). |
struct sockaddr_in server_addr, client_addr;
client_addr_len indica el tamaño de la estructura client_addr y es necesario para funciones como recvfrom() y sendto() para gestionar correctamente las direcciones del cliente. |
socklen_t client_addr_len = sizeof(client_addr);
socket(AF_INET, SOCK_DGRAM, 0): Crea un socket UDP: AF_INET: Usa direcciones IPv4. SOCK_DGRAM: Define el socket como sin conexión (UDP). 0: Selecciona el protocolo predeterminado para UDP. |
// Creating socket file descriptor
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
Se configura la estructura server_addr para que el servidor reciba mensajes UDP en IPv4, en cualquier interfaz de red local y en el puerto especificado. * Es una configuración estándar (no personalizada) necesaria para el funcionamiento de la conexión. |
// Setting up the server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
Esta línea enlaza el socket al puerto y dirección configurados. Si falla, muestra un error y termina el programa.
sockfd: Descriptor del socket creado previamente. Identifica el socket que se va a enlazar a una dirección y puerto. (struct sockaddr *)&server_addr: Dirección y puerto a los que el socket se enlaza. server_addr contiene: sin_family: IPv4 (AF_INET). sin_addr.s_addr: Acepta mensajes de cualquier IP (INADDR_ANY). sin_port: Puerto configurado para el servidor (htons(PORT)). El cast (struct sockaddr *) adapta el tipo específico sockaddr_in al genérico sockaddr. sizeof(server_addr): Indica el tamaño de la estructura server_addr para que bind() lea correctamente toda la información. |
// Binding the socket
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d...\n", PORT);
while (1) {
// Receiving a message from the client
recvfrom(): Recibe un mensaje enviado por un cliente: sockfd: Descriptor del socket. buffer: Espacio para almacenar el mensaje recibido. BUFFER_SIZE: Tamaño máximo que puede recibir. 0: Opciones adicionales (generalmente 0). (struct sockaddr *)&client_addr: Dirección del cliente que envió el mensaje (se almacena aquí). &client_addr_len: Tamaño de la estructura de la dirección del cliente. n: Cantidad de bytes recibidos. |
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client_addr, &client_addr_len);
buffer[n] = '\0'; // Null-terminate the received message
printf("Message received from client: %s\n", buffer);
// Sending a response back to the client
const char *response = "Hello from the UDP server!";
sendto(): Envía el mensaje al cliente. sockfd: Descriptor del socket usado para enviar datos. response: Mensaje que se quiere enviar. strlen(response): Longitud del mensaje en bytes. 0: Opciones adicionales (usualmente 0 para envío estándar). (struct sockaddr *)&client_addr: Dirección del cliente que recibirá el mensaje. client_addr_len: Tamaño de la estructura de dirección del cliente. |
sendto(sockfd, response, strlen(response), 0, (struct sockaddr *)&client_addr, client_addr_len);
printf("Response sent to client.\n");
}
close(sockfd);
return 0;
}
// Cliente UDP en Linux:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
char buffer[BUFFER_SIZE];
struct sockaddr_in server_addr;
addr_len almacena el tamaño de server_addr. Es necesario para que las funciones de sockets sepan cuánta memoria deben manejar al trabajar con la dirección del servidor. |
socklen_t addr_len = sizeof(server_addr);
const char *message = "Hello from the UDP client!";
// Creating socket file descriptor
socket(AF_INET, SOCK_DGRAM, 0): Crea un socket UDP: AF_INET: Protocolo IPv4. SOCK_DGRAM: Define el socket como orientado a datagramas (UDP, sin conexión). 0: Selecciona el protocolo predeterminado para SOCK_DGRAM, que es UDP.
|
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
Se configura la estructura server_addr para que el servidor reciba mensajes UDP en IPv4, en cualquier interfaz de red local y en el puerto especificado. * Es una configuración estándar (no personalizada) necesaria para el funcionamiento de la conexión. |
// Setting up the server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("Invalid address or address not supported");
close(sockfd);
exit(EXIT_FAILURE);
}
// Sending a message to the server
sendto(): Envía un mensaje al servidor utilizando el socket UDP. sockfd: Descriptor del socket desde el cual se envía el mensaje. message: El mensaje que se quiere enviar (en este caso, una cadena de texto). strlen(message): Tamaño del mensaje en bytes (longitud de la cadena). 0: Opciones adicionales (generalmente 0 para envío estándar). (struct sockaddr *)&server_addr: Dirección y puerto del servidor al que se envía el mensaje. addr_len: Tamaño de la estructura de dirección server_addr. |
sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_addr, addr_len);
printf("Message sent to server: %s\n", message);
*) recvfrom() espera recibir un mensaje desde el servidor, lo guarda en buffer, y también almacena la dirección del servidor en server_addr. El tamaño del mensaje recibido se almacena en n. |
// Receiving a response from the server
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len);
buffer[n] = '\0'; // Null-terminate the received message
printf("Message received from server: %s\n", buffer);
close(sockfd);
return 0;
}
Paso | TCP | UDP |
|---|
Crear el socket | socket(AF_INET, SOCK_STREAM, 0) | socket(AF_INET, SOCK_DGRAM, 0) |
Configurar la dirección | Configurar sockaddr_in (IP, puerto) | Configurar sockaddr_in (IP, puerto) |
Enlazar el socket (bind) | bind() (servidor) | bind() (servidor) |
Establecer conexión (cliente) | connect() (cliente) | No necesario |
Escuchar conexiones (servidor) | listen() (servidor) | No necesario |
Aceptar conexiones (servidor) | accept() (servidor) | No necesario |
Enviar datos | send() | sendto() |
Recibir datos | recv() | recvfrom() |
Cerrar conexión | close() | close() |