Código
#include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <time.h> #include <sys/types.h> #include <stdbool.h> #define MAX_dani 0xF0000 struct params{ /* En esta estructura se almacenan los parametros de la funcion t*/ char web[20]; // Dominio web int port; // Puerto (sera el 80, para peticiones HTTP) int thread; // El numero de thread int nrequests; // El numero de peticiones int sleeptime; // El tiempo de espera entre cada peticion }; int total_requests; // Para almacenar el numero total de peticiones pthread_mutex_t lock; // Para evitar que varios threads modifiquen total_requests a la vez int nthreads; // Numero de threads a crear void* t(void *p) /* Esta es la funcion que va a ejecutar cada thread*/ { int n = ((struct params*)p)->thread+1; // El numero de thread char request[128]; // Para almacenar la peticion _Bool connected; // Variable auxiliar, indica si el socket esta conectado struct hostent *host = gethostbyname(((struct params*)p)->web); // Obtener la IP de la web if(!host) { return NULL; } /*Para getpeername()*/ struct sockaddr sockbuf; int stsize = sizeof(sockbuf); /*Preparar los datos de la conexion */ struct sockaddr_in sock; sock.sin_family = AF_INET; sock.sin_port = htons(((struct params*)p)->port); sock.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)host->h_addr))); int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Creamos el socket if(sockfd==-1) { return NULL; } int aux; connect(sockfd, (struct sockaddr*) &sock, sizeof(struct sockaddr)); // Conectamos connected=true; sprintf(request, "GET / HTTP/1.1\nHost: %s\nUser-Agent: Mozilla/4.0\n\n ", host->h_name); // Ponemos la peticion en una cadena for(aux=0; aux<(((struct params*)p)->nrequests); aux++) { if(getpeername(sockfd, &sockbuf, &stsize)<0) // Comprobar que el socket esta conectado { if(errno==ENOTCONN) // Si no lo esta, cerrar y reconectar close(sockfd); sockfd = socket(AF_INET, SOCK_STREAM, 0); if(connect(sockfd, (struct sockaddr*) &sock, sizeof(struct sockaddr))==-1) { connected=false; break; } } if(!connected) // Si no se pudo reconectar, decrementar aux y reiniciar el bucle { aux--; continue; } pthread_mutex_lock(&lock); // Incrementar el numero total de peticiones total_requests++; pthread_mutex_unlock(&lock); sleep(((struct params*)p)->sleeptime); // Pausar } close(sockfd); // Cerrar el socket pthread_exit(NULL); // Salir } int main(int argc, char *argv[]) { /*Tratamiento de linea de comandos*/ if(argc!=6) { printf("Uso: %s numero_de_threads dominio_web puerto(80) numero_de_peticiones_por_thread tiempo_de_espera\n", argv[0]); } /*Inicializar algunas estructuras y parametros*/ pthread_mutex_init(&lock, NULL); pthread_attr_t a; int i, ret, j; // Algunas variables auxiliares for(j=0; j<nthreads; j++) { p[j].thread = j; } /*Setear la cantidad de memoria que un thread puede usar*/ pthread_attr_init(&a); pthread_attr_setstacksize(&a, MAX_dani); /*Saber el tiempo que hace que se inicio el programa*/ /*Crear los threads*/ for(i=0; i<nthreads; i++) { ret = pthread_create(&mythreads[i], &a, t, &p[i]); switch(ret) { case 0: break; case EAGAIN: _exit(1); case EINVAL: _exit(2); case EPERM: _exit(3); } } /*Esperar a que terminen los threads, liberar memoria y mostrar algunas estadisticas aproximadas*/ pthread_attr_destroy(&a); for(j=0; j<nthreads; j++) pthread_join(mythreads[j], NULL); pthread_mutex_destroy(&lock); return 0; }
Saludos!