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

Upload New File

parent 116704d0
No related branches found
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
// Funcion 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);
}
}
// Funcion 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, "Numero de puerto invalido: %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 = 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