Skip to content
Snippets Groups Projects
Commit fc046d99 authored by danredo's avatar danredo
Browse files

Delete daytime-tcp-server-L110.c

parent b81c6e55
Branches
No related tags found
No related merge requests found
/**
* Practica Tema 6: DAYTIME TCP
*
* Redondo Calleja, Daniel
* Jimenez Prieto, Roberto
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h> // Para getservbyname()
#include <signal.h> // Para manejar señales
#include <sys/socket.h> // Para sockets
#include <netinet/in.h> // Para estructuras de sockets
#include <errno.h>
#include <sys/wait.h> // Para waitpid()
#include <stdbool.h> // Para boolean
#define BUFF_SIZE 256
#define DEFAULT_SERVICE "daytime"
int server_sockfd; // Socket principal del servidor
// Función para obtener la hora actual utilizando el comando "date"
void get_date(char *buffer, size_t longitud) {
FILE *file;
system("date > /tmp/date.txt"); // Ejecuta date y guarda la salida en un temporal date.txt
file = fopen("/tmp/date.txt", "r"); // Verificamos que se ha creado date.txt
if (file == NULL || fgets(buffer, longitud, file) == NULL) {
perror("Error al obtener la fecha con system() o fopen()");
exit(EXIT_FAILURE);
}
fclose(file);
}
// Manejador de señal para cerrar los sockets al recibir Ctrl+C (SIGINT)
void signal_handler(int signal) {
if (signal == SIGINT) {
printf("\nServidor TCP cerrando conexiones...\n");
close(server_sockfd); // Cerrar el socket principal del servidor
exit(EXIT_SUCCESS);
}
}
// Función para manejar las conexiones de los clientes en procesos hijos
void manejar_cliente(int client_sockfd) {
char buffer[BUFF_SIZE], date_buffer[BUFF_SIZE];
char hostname[BUFF_SIZE];
// Obtenemos el nombre del host
if (gethostname(hostname, sizeof(hostname)) < 0) {
perror("Error al obtener el nombre del servidor");
close(client_sockfd);
exit(EXIT_FAILURE);
}
// Obtenenemos la fecha y hora actual
get_date(date_buffer, BUFF_SIZE);
// Prepararamos la respuesta en formato "nombre: fecha"
snprintf(buffer, BUFF_SIZE, "%s: %s", hostname, date_buffer);
// Enviamos la respuesta al cliente
if (send(client_sockfd, buffer, strlen(buffer), 0) < 0) {
perror("Error al enviar la respuesta al cliente");
}
// Cerramos el socket del cliente
close(client_sockfd);
exit(EXIT_SUCCESS);
}
// Función principal del servidor TCP
int main(int argc, char *argv[]) {
int port, reutil = 1;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
bool continua = true;
// Configuramos el manejador de señal para SIGINT
signal(SIGINT, signal_handler);
// Obtenemos el puerto por argumento
if (argc == 3 && strcmp(argv[1], "-p") == 0) {
port = atoi(argv[2]);
if (port <= 0) {
fprintf(stderr, "Número de puerto inválido: %d\n", port);
return EXIT_FAILURE;
}
// O lo obtenemos por getservbyname() dando el servicio "daytime"
} else if (argc == 1) {
struct servent *service = getservbyname("daytime", "udp");
if (service == NULL) {
fprintf(stderr, "Error al obtener el puerto para el servicio DAYTIME\n");
return EXIT_FAILURE;
}
port = htons(service->s_port);
// Si no lo hemos obtenido, notificamos el error
} else {
fprintf(stderr, "Error de Parametros.\nUso: %s [-p puerto]\n", argv[0]);
return EXIT_FAILURE;
}
// Creamos el socket TCP
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Error al crear el socket");
return EXIT_FAILURE;
}
// Configuramos la dirección del servidor
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
// Habilitamos reutilización de direcciones para evitar el problema de puerto en TIME_WAIT
setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &reutil, sizeof(reutil));
// Vinculamos el socket al puerto
if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Error en bind()");
close(server_sockfd);
return EXIT_FAILURE;
}
// Ponemos el socket en modo escucha
if (listen(server_sockfd, 10) < 0) {
perror("Error en listen()");
close(server_sockfd);
return EXIT_FAILURE;
}
// Imprimimos un mensaje para verificar que se ha creado correctamente
printf("Servidor TCP Daytime en el puerto %d\n", port);
while (continua) {
// Aceptamos conexiones entrantes
int client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_len);
if (client_sockfd < 0) {
if (errno == EINTR) { // Interrupción por señal, salir del bucle
continua = false; // Cambiamos continua a false para salir del bucle
continue;
}
perror("Error en accept()");
continue;
}
// Creamos un nuevo proceso para manejar al cliente
pid_t pid = fork();
if (pid < 0) {
perror("Error en fork()");
close(client_sockfd);
} else if (pid == 0) { // Proceso hijo: manejar al cliente
close(server_sockfd); // El proceso hijo no necesita el socket del servidor
manejar_cliente(client_sockfd);
} else { // Proceso padre: cerrar el socket del cliente
close(client_sockfd);
// Limpia procesos hijos finalizados
while (waitpid(-1, NULL, WNOHANG) > 0);
}
}
shutdown(server_sockfd, SHUT_RDWR);
close(server_sockfd); // Cerramos el socket principal al salir del bucle
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment