Contenidos
En este tutorial, exploraremos cómo realizar programación de sockets en C en el entorno Linux. La programación de sockets permite que los programas se comuniquen a través de una red utilizando protocolos como TCP e UDP.
¿Qué es un socket?
Un socket es un punto final en una comunicación entre dos programas a través de una red. Los sockets permiten que los datos se transmitan entre procesos en la misma máquina o en máquinas diferentes utilizando protocolos de comunicación.
Tipos de sockets
- Sockets de flujo (Stream Sockets): Utilizan el protocolo TCP para una comunicación orientada a conexión y confiable.
- Sockets de datagramas (Datagram Sockets): Utilizan el protocolo UDP para una comunicación sin conexión y sin garantía de entrega.
Programación de un socket TCP
A continuación, se muestra cómo implementar un servidor y un cliente usando sockets TCP.
1. Servidor TCP
Primero, crearemos un servidor que escuche en un puerto y acepte conexiones de clientes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// Crear el socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Configurar la dirección del servidor
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// Enlazar el socket
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// Escuchar por conexiones
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// Aceptar una conexión
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// Leer datos del cliente
read(new_socket, buffer, BUFFER_SIZE);
printf("Mensaje del cliente: %s\n", buffer);
// Enviar una respuesta al cliente
send(new_socket, "Hola desde el servidor", strlen("Hola desde el servidor"), 0);
printf("Mensaje enviado al cliente\n");
// Cerrar el socket
close(new_socket);
close(server_fd);
return 0;
}
2. Cliente TCP
Ahora, crearemos un cliente que se conecte al servidor y envíe un mensaje.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char *message = "Hola desde el cliente";
char buffer[BUFFER_SIZE] = {0};
// Crear el socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket creation error");
exit(EXIT_FAILURE);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convertir IPv4 e IPv6 direcciones desde texto a binario
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
perror("invalid address / address not supported");
exit(EXIT_FAILURE);
}
// Conectar al servidor
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("connection failed");
exit(EXIT_FAILURE);
}
// Enviar un mensaje al servidor
send(sock, message, strlen(message), 0);
printf("Mensaje enviado al servidor\n");
// Leer la respuesta del servidor
read(sock, buffer, BUFFER_SIZE);
printf("Respuesta del servidor: %s\n", buffer);
// Cerrar el socket
close(sock);
return 0;
}
Programación de un socket UDP
Ahora, implementaremos un servidor y un cliente utilizando sockets UDP.
1. Servidor UDP
El servidor UDP recibirá mensajes de clientes y enviará una respuesta.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
char buffer[BUFFER_SIZE] = {0};
// Crear el socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// Enlazar el socket
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// Recibir mensaje del cliente
recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client_addr, &addr_len);
printf("Mensaje recibido del cliente: %s\n", buffer);
// Enviar una respuesta al cliente
sendto(sockfd, "Hola desde el servidor UDP", strlen("Hola desde el servidor UDP"), 0, (struct sockaddr *)&client_addr, addr_len);
printf("Respuesta enviada al cliente UDP\n");
// Cerrar el socket
close(sockfd);
return 0;
}
2. Cliente UDP
El cliente UDP enviará un mensaje al servidor y recibirá una respuesta.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr;
char *message = "Hola desde el cliente UDP";
char buffer[BUFFER_SIZE] = {0};
// Crear el socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// Convertir IPv4 e IPv6 direcciones desde texto a binario
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("invalid address / address not supported");
exit(EXIT_FAILURE);
}
// Enviar un mensaje al servidor
sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
printf("Mensaje enviado al servidor UDP\n");
// Recibir una respuesta del servidor
recvfrom(sockfd, buffer, BUFFER_SIZE, 0, NULL, NULL);
printf("Respuesta del servidor UDP: %s\n", buffer);
// Cerrar el socket
close(sockfd);
return 0;
}
Consideraciones
La programación de sockets es fundamental para crear aplicaciones de red. TCP proporciona una comunicación confiable, mientras que UDP es más adecuado para aplicaciones que requieren velocidad y pueden tolerar pérdidas de datos.

