rss
Rechercher : dans
Par : Pertinence Date Nom d'utilisateur
Statut : Résolu

[C] Programmation réseau et socket

Posté par jro-daemon, le mardi 13 février 2007 à 23:24:29
Bonjour,
je suis actuellement en train de m'attaquer à l'apprentissage de l'utilisation de socket. Je travaille sous Ubuntu Edgy. J'ai deja fait le test de faire communiquer un client et un serveur en utilisant la boucle locale. Ma question est de savoir s'il est possible que je fasse tourner un client et un serveur dans un même programme en utilisant les descripteurs de fichiers.
Mon idée est la suivante:
Tout d'abord je crée un set de descripteur de fichiers avec:
fd_set master
int fd_max

Puis dans le fichier principal, je taperais un truc de ce genre:
#define PORT_CLIENT 5060
#define PORT_SERVER 7000

int client_fd;
int server_fd;
fd_set read_fds;
struct timeval tv;
/*
J'utilise ici la structure timeval pour fixer un timeout à 10 ms
*/
tv.tv_sec = 0;
tv.tv_usec = 10;

FD_ZERO(&master);
FD_ZERO(&read_fds);
/*
J'initialise ici un descripteur de fichier pour le serveur et le client. Les procédures client_start() et server_start() retournent ce socket.
*/
client_fd = client_start(PORT_CLIENT); 
server_fd = server_start(PORT_SERVER);

FD_SET(client_fd,&master);
FD_SET(server_fd,&master);
FD_SET(0,&master);

/*...*/

/*Boucle principale*/
while(1)
{
 read_fds = master;
 if (pselect(fdmax+1,&read_fds,NULL,NULL,&tv,NULL) <0)
 /*controle d'erreur*/
 if (FD_ISSET(0,&read_fds)) // On lit quelque chose dans le descripteur de fichier de stdin
{
/*Action a entreprendre en conséquence*/
}
if(FD_ISSET(client_fd,&read_fds))
{
 /*Le client a reçu quelque chose provenant du serveur, il répond en conséquence*/
}
if (FD_ISSET(server_fd,&read_fds))
{
/*Le serveur reçoit un message provenant du client, il réagit en conséquence en traitant le message dans la partie application*/
}
}

Lire l'entrée de stdin permet de sortir de la boucle infinie. Est-ce que l'idée pourrait marcher?
Johnny
Configuration: Linux
Firefox 2.0.0.1
Répondre à jro-daemon  Signaler ce message aux modérateurs Aller au dernier message

1


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le mercredi 14 février 2007 à 09:26:16
Salut.
Je n'ai pas compris ce que tu voulais faire.
Mais je ne voi aucun problème à avoir un programme qui fait à la foi client et serveur. En fait, c'est une espèce de logiciel routeur.
Moi, j'ai fait un programme qui fait plusieurs clients.
par contre, je gèrerai ça en thread plutôt qu'en while if. Salutation !
Char Snipeur
Répondre à Char Snipeur

2


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
jro-daemon, le mercredi 14 février 2007 à 12:36:18
Bonjour,
l'idée serait donc de le faire avec des threads. C'est-à-dire qu'il y aurait un thread pour le client et en pour le serveur. As-tu par hasard un lien sur les applications multi-thread histoire que je voie comment ça marche. Peux-tu me donner un exemple concret d'utilisation pour que je pige bien la mise en pratique?
Merci pour l'idée. Je vais continuer à réfléchir dans ce sens.
Johnny
Répondre à jro-daemon

3


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le jeudi 15 février 2007 à 08:52:11
regarde ça :
http://khayyam.developpez.com/articles/cpp/multithreads/
je pense que ça correspond bien Salutation !
Char Snipeur
Répondre à Char Snipeur

4


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
jro-daemon, le vendredi 16 février 2007 à 00:08:06
Salut,
Je me suis renseigné et implémenter un code en utilisant un processus fils créé avec
fork()
pour s'occuper d'un nouveau client.
Et aussi, dans mon cas, si je veux faire tourner un client et un serveur dans le même programme, il est vrai que les threads sont plus adaptés.
Lorsque je reçois une requête d'un client, je lance le thread du serveur et il la traite puis si je reçois une réponse d'un serveur, je lance le thread du client tout ça en veillant à ne pas écraser des éventuelles données partagées en utilisant l'exclusion mutuelle. Je crois que ça pourrait bien se goupiller.
Merci pour ton exemple.

Cordialement,
Johnny D.
Répondre à jro-daemon

5


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Stupeflip, le vendredi 16 février 2007 à 11:38:25
Coucou, évite d'utiliser fork() si tu peux, pour plusieurs raisons:

-fork réplique la totalité du processus, il est donc bcp plus lourd
-les données à communiquer entre père et fils sont bien plus dures à communiquer qu'avec les threads
-coder avec fork c est moche

Sous Linux, tu peux utiliser pthread.h qui est super et très facile à prendre en main. Je peux te poster un exemple de serveur multi protocle et multi client si tu as besoin.
Répondre à Stupeflip

6


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
jro-daemon, le vendredi 16 février 2007 à 13:31:05
Salut,
En comparant les deux méthodes, je pense que tes reamarques sont tout à fait judicieuses. Merci. Les threads, j'en avais jamais manipulés avant mais je pense que c'est très avantageux. Il faut par contre prendre ces précautions face aux variables partagées. Mais quand on en a pas, on s'en fout. Chaque tâche peut tourner dans un thread indépendant en se partageant les ressources mémoire du processus en cours, c'est bien ça l'idée qui est derrière le partage?
J'aimerais bien que tu me postes ton exemple, stp.
Cordialement,
Johnny D.
Répondre à jro-daemon

7


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Stupeflip, le vendredi 16 février 2007 à 13:46:55
Oui les threads partagent le meme adressage memoire. Ainsi le plus simple (mais c'est assez dangereux dans un programme complexe, et puis c est pas tres propre), c est d utiliser des variables globales. Tout les threads y ont acces et tous peuvent ecrire. Cependant des que tu as des fonctions concurrentes, cela pose probleme. Tu peux alors utiliser des flags (blocage de la valeur le temps qu une fonction y accede) ou des semaphores. Il y a d'autres utilisations pour l exclusion mutuelle mais ces deux là sont faciles a prendre en main (en tout cas sous Linux !). Je te post le code du main d un serveur que j ai fait l annee derniere, c est donc assez recent ;)

int main()
{
	/* Variables Network */
   	struct sockaddr_in sin1;
   	struct sockaddr_in sin2;
   	struct sockaddr_in cliaddr1,cliaddr2;
   	struct sigaction sa;
   	int fd1,new_fd1;
   	int fd2,new_fd2;
   	int address_size;
   	int maxfd;
    pid_t childpid;
   	socklen_t clilen1,clilen2;
   	fd_set rset;
   	pthread_t w1;
   	pthread_t server_th;
   	pthread_t server_th2;
	
	/* Variables Video */
   	char *videodevice = "/dev/video0";
   	int format = VIDEO_PALETTE_YUV420P;
   	int width = 640;
   	int height = 480;

	/* Variables Temp */
   	char buf[16384];
   	int err,re,i,len;
	
	/* Initialisation de la video en mode mmap par defaut */
   	printf("%sVideo initialization in progress ...%s\n",ppurple,pnormal);
	memset (&videoIn, 0, sizeof (struct vdIn));
	if (init_videoIn(&videoIn, videodevice, width, height, format,1) != 0)
     		printf ("%sInitialisation error !%s\n",pred,pnormal);
	printf("%sVideo initialization correctly done !%s\n",ppurple,pnormal);
    
  	/* Creation du thread pour le Grab */
	if((err= pthread_create (&w1, NULL, (void *) grab, NULL)) != 0)
	{
		printf("%sGrab creation thread error %d %s\n",pred,err,pnormal);
		close_v4l (&videoIn);
		exit(1);
 	}

	/* Socket UDP */
  	if((fd1=socket(AF_INET,SOCK_DGRAM,0))==-1)
    		erreur("socket");
 
	/* Socket TCP */
   	if((fd2=socket(AF_INET,SOCK_STREAM,0))==-1)
     		erreur("socket");
		
   	bzero(&sin1,sizeof(sin1));
   	sin1.sin_family=AF_INET;
   	sin1.sin_addr.s_addr=INADDR_ANY;
   	sin1.sin_port=htons(port1);

   	bzero(&sin2,sizeof(sin2));
   	sin2.sin_family=AF_INET;
   	sin2.sin_addr.s_addr=INADDR_ANY;
   	sin2.sin_port=htons(port2);

	printf("%sBinding ...%s\n",pgreen,pnormal);
   	if(bind(fd1,(struct sockaddr*)&sin1,sizeof(sin1))==-1)
   		erreur("bind");
   	if(bind(fd2,(struct sockaddr*)&sin2,sizeof(sin2))==-1)
   		erreur("bind");
		
	printf("%sListening ...%s\n",pgreen,pnormal);
   	if(listen(fd2,20)==-1)
  		erreur("listen");
 
   	/* Ignore sigpipe */
    	signal(SIGPIPE, SIG_IGN);	

    	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;

    	printf("%sWaiting for connection ...%s\n",pblue,pnormal);
    
    	signal(SIGCHLD,sig_handle);
    	FD_ZERO(&rset);
         
	/* Beginning Client Loop */                                                                        
    	for(;;)
    	{
      		FD_SET(fd1,&rset);
     		FD_SET(fd2,&rset);
      		maxfd=max(fd1,fd2)+1;
      		if (select(maxfd,&rset,NULL,NULL,NULL)<0)
      		{
        		if(errno==EINTR)
         			continue;
        		else
        		{
         			printf("Select error : %s\n",strerror(errno));
         			exit(1);
        		}
		}
		/* Socket UDP */
     		if(FD_ISSET(fd1,&rset))
      		{
       			//printf("%s[%sUDP%s] Connection acquired from (%s%s%s)%s\n",pblue,pred,pblue,ppurple,inet_ntoa(cliadd­r1.sin_addr),pblue,pnormal);
			pthread_create(&server_th2, NULL, (void *)service_udp, &fd1);
     		}
   
   		/* Socket TCP */
      		if(FD_ISSET(fd2,&rset))
      		{
       			clilen2=sizeof(cliaddr2);
       			if((new_fd2=accept(fd2,(struct sockaddr*)&cliaddr2,&clilen2))<0)
       			{
         			if(errno==EINTR)
          			continue;
          			else
          			{
           				printf("accept error \n");
           				exit(1);
          			}
       			}
			printf("%s[%sTCP%s] Connection acquired from (%s%s%s)%s\n",pblue,pred,pblue,ppurple,inet_ntoa(cliadd­r2.sin_addr),pblue,pnormal);
	
			/* Creation d'un thread par client */
         		pthread_create(&server_th, NULL, (void *)service, &new_fd2);
		}
     	} /* Fin du For */
	
	/* En attente de l'arret du thread Grab */
      	pthread_join (w1, NULL);
	
	/* Fermeture programme */
      	close(fd1);
      	close(fd2);
      	close_v4l (&videoIn);
      	exit(0);
}
Répondre à Stupeflip

8


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Char Snipeur, le vendredi 16 février 2007 à 15:54:59
NOTE : pthread existe aussi sous windows
Répondre à Char Snipeur

9


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Stupeflip, le vendredi 16 février 2007 à 16:04:31
Oui mais ce n'est qu'une adaptation de la norme POSIX qui est fait pour Linux et d'ailleurs c'est mal adapté à mon gout (je précise :p) car ayant voulu mettre des thread sous windows en utilisant pthread j'ai eu une désagréable surprise (et oui Visual C++ encore une fois).

Heureusement l'auteur du post est sous Linux donc tout va bien pour lui ;)
Répondre à Stupeflip

10


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
jro-daemon, le samedi 17 février 2007 à 01:03:40
Salut,
en effet, je suis bien sous linux lorsque je fais de la programmation et en général je me suis bien habitué à travailler sur la récente version d'Ubuntu. Et puis, sous Windows, j'ai jamais vraiment fait de la prog sauf une fois lorsque j'avais à programmer une puce donc c'était mieux de le faire sous Windows. Sinon, j'aime pas trop les interfaces et j'ai pas cherché s'il y avait des IDE intéressantes sous Windows: peut être Visual C++, mais l'ayant utilisé quelquefois, je le trouve pas à mon goût.
Bonne nuit,
Johnny D.
Répondre à jro-daemon

11


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
The Incredible JSG, le dimanche 18 février 2007 à 13:47:12
Bonjour,


j'ai écrit un tutoriel qui explique comment utiliser les fonctions sockets, aussi bien sous Linux que sous Windows :

http://www.quantic-storm.com/qs/index.php?menu=Community&sm0­=Sockets&language=FR

Tout le code est téléchargeable, ainsi qu'un exemple de client-serveur. Celui-ci utilise bien des threads (un par client ou par serveur) et le tout troune dans la même application. Le code se compile aussi bien sous Windows que sous Linux (testé avec Ubuntu).
Répondre à The Incredible JSG

12


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
jro-daemon, le samedi 24 février 2007 à 19:08:48
Oui, merci pour ton information. La librairie est une API utilisable pour n'importe quel type d'application, n'est-ce-pas? Je pense que je pourrais m'en servir pour développer une application fonctionnant avec le protocole SIP.
Cordialement,
Johnny
Répondre à jro-daemon

13


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
 nanou, le vendredi 11 janvier 2008 à 11:33:06
slt
je cherche de la doc sur winsock
je debute en programmation socket
Répondre à nanou
Logiciels pertinents trouvés dans les téléchargements
Télécharger Ultimate Boot CD 4.1.1Ultimate Boot CD - Ultimate Boot CD (UBCD) est un CD bootable contenant une panoplie d'outils pouvant se révéler d'une grande utilité lorsque...Catégorie: Système
Licence: Freeware/gratuit
Télécharger Casc'ADSL 0.99 build 4209Casc'ADSL - Casc'ADSL est un outil destiné aux Internautes se connectant via le service d'accès distant et désireux de maintenir leur...Catégorie: ADSL
Licence: Freeware/gratuit
Télécharger CounterSpy 2.1.946CounterSpy - Conterspy est un excellent antispyware très complet qui en plus d'immuniser votre PC contre les menaces d'Internet, vous...Catégorie: Anti-Spyware
Licence: Shareware
Télécharger Cobian Backup 8.4.0.202Cobian Backup - Cobian Backup est une application multitâche permettant de planifier une sauvegarde automatique de fichiers ou répertoires...Catégorie: Sauvegarde
Licence: Open Source
Plus de logiciels gratuits sur « [C] Programmation réseau et socket »