sioux.c 3.48 KB
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pthread.h>

#define BUFF_SIZE 1000


int initialisationServeur(char* service)
{
	int sock_fd;

	struct addrinfo precisions, *resultat=NULL, *origine; // On stocke dans précisions nos besoins pour le socket, dans resultat l'adresse qui respectera les reqêtes

	memset(&precisions, 0, sizeof precisions);
	precisions.ai_family = AF_UNSPEC;
	precisions.ai_socktype = SOCK_STREAM;
	precisions.ai_flags = AI_PASSIVE;
	
	if(getaddrinfo(NULL, service, &precisions, &origine)<0) { fprintf(stderr, "Erreur getaddrinfo\n"); return(-1); }
	
	int n=0;
	
	for(struct addrinfo* i=origine; i!=NULL && resultat==NULL; i=i->ai_next)
	{
		printf("%d - ", n);
		if(i->ai_family==AF_INET)
		{
			resultat=i;
			printf("Test : %d", origine->ai_addrlen);
		}

		printf("\n");	
		n++;
	}

	struct sockaddr_in* test=(struct sockaddr_in*)(resultat->ai_addr);
	printf("Addr : %x\n", test->sin_addr.s_addr);
	if((sock_fd=socket(resultat->ai_family, resultat->ai_socktype, resultat->ai_protocol))<0) { fprintf(stderr, "Erreur socket\n"); return(-1); }

	int val=1;
	
	if(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR|SO_BROADCAST, &val, sizeof(val))<0) { fprintf(stderr, "Erreur setsockopt\n"); return(-1); }



	if(bind(sock_fd, resultat->ai_addr, resultat->ai_addrlen)) { fprintf(stderr, "Erreur bind\n"); return(-1); }

	if(listen(sock_fd, 20) < 0) { fprintf(stderr, "Error listen server socket\n"); return (-1); }
	
	freeaddrinfo(origine);
	
	return sock_fd;
}


void* reponseConnexion(void* sock)
{
	
	printf("Connected\n");
	char buffer[BUFF_SIZE];
	
	FILE* sockdial_stream = fdopen(*((int*)(sock)), "a+");
	
	printf("Sock : %d // Stream : %p \n", *((int*)(sock)), sockdial_stream);

	while(strcmp(buffer, "EXIT\n")!=0)
	{
		printf("WAIT\n");
		fgets(buffer, BUFF_SIZE, sockdial_stream);
	
		printf("Le message reçu : %s", buffer);

		fprintf(sockdial_stream, "Ceci est une réponse du serveur TCP.\n");

	}

	strcpy(buffer, "START");	
	printf("Fin de la connexion\n");
	fclose(sockdial_stream);
	pthread_exit(NULL);
}


int lanceThread(void(* fonction) (void *), void* arg, int size)
{
	pthread_t thr_id;
	
	if(pthread_create(&thr_id, NULL, (void*)fonction, arg )!=0) { fprintf(stderr, "Le thread n'a pas pu être créé.\n"); return -1; }
	
	pthread_detach(thr_id);

	return 0;
}


int boucleServeur(int socket, void(* fctConnex)(int))
{
	int sock_dial;

	printf("------- Début boucle serveur TCP -------\n\n");
	
	while(1)	
	{
		printf("-- boucle --\n");
		if((sock_dial=accept(socket, NULL, NULL)) < 0){ fprintf(stderr, "Error accept dialogue\n"); return -1; }
		printf("Dialogue ACCEPTED\n");

		lanceThread((void*)fctConnex, (void*)&sock_dial, sizeof(sock_dial));
	}
}


void argPortParsing(int argc, char* argv[], char* port)
{
	struct option port_arg={"port", 1, NULL, 'p'};
	char opt;
	int longindex;

	while( (opt=getopt_long(argc, argv, "p:", &port_arg, &longindex)) !='p' && opt!=-1) {}

	if(opt=='p') 
	{
		strcpy(port, optarg);
		printf("%s\n", optarg);
	}
	else
	{
		printf("La syntaxe doit être de la forme ./sioux -p <port> ou ./sioux --port <port>\n\n");
	}
}


int main(int argc, char* argv[])
{
	char port[10]="80";
	argPortParsing(argc, argv, port);
	

	int sock_fd=initialisationServeur(port);

	if( sock_fd==-1 ) { fprintf(stderr, "Initialisation du serveur impossible\n"); return -1; }


	boucleServeur(sock_fd, (void*)&reponseConnexion);

	return 0;
}