[C] Un chat simple en C

Un chat simple en C [C] - C - Programmation

Marsh Posté le 01-04-2004 à 19:00:27    

Salut à tous!
J'ai besoin de faire un chat très simple en ligne de commande en C, avec un serveur et plusieurs clients.
Voilà en gros mon code (inspiré de CPPFrance):

Code :
  1. server=socket(AF_INET,SOCK_STREAM,0);
  2. bind(server,(SOCKADDR*)&sinserv,sizeof(sinserv));
  3. listen(server,0);
  4. char buffer[N];
  5. memset(buffer,0,sizeof(buffer));
  6. int sinsize;
  7. int err=0;
  8. while(1)
  9.     {
  10.      sinsize=sizeof(sin);
  11.     if((sock=accept(server,(SOCKADDR*)&sin,&sinsize))!=INVALID_SOCKET)
  12.         {
  13.               while(1)
  14.               { 
  15.                 recv(sock,buffer,sizeof(buffer),0);
  16.                 printf("%s\n",buffer);
  17.         }
  18.       }
  19.     }


Le problème, c'est que quand un nouveau client vient se connecter, le serveur est déjà dans sa boucle infinie en attendant de reçevoir des infos du premier client.
Comment je peux faire pour séparer les différents clients?
Je suis sous windows, je dois utiliser des threads?

Reply

Marsh Posté le 01-04-2004 à 19:00:27   

Reply

Marsh Posté le 01-04-2004 à 19:21:15    

Moi c'est ce que je fais effectivement, dès qu'il y a une connection j'ouvre un thread.
Sinon il faut utiliser select avec un time-out je pense, mais c'est moins pratique.

Reply

Marsh Posté le 01-04-2004 à 19:22:14    

le problème avec un thread, c'est que je dois passer quoi en argument pour récupérer le socket qui a été ouvert?

Reply

Marsh Posté le 01-04-2004 à 19:23:08    

passe un pointeur sur une structure avec les données dont tu as besoin.

Reply

Marsh Posté le 01-04-2004 à 19:26:32    

je peux pas juste passer le sock en argument?

Reply

Marsh Posté le 01-04-2004 à 19:34:25    

si bien sûr, si tu n'as besoin que de ça ;)

Reply

Marsh Posté le 01-04-2004 à 19:59:10    

ok je vais essayer...

Reply

Marsh Posté le 01-04-2004 à 20:52:26    

sizeof variable
sizeof(Type)

Reply

Marsh Posté le 01-04-2004 à 23:55:09    

j'ai essayé de faire
pthread_create(&thread1, NULL, (void*)&thread_serveur, (void*) sock);
 
mais je crois que j'ai un pb du côté de mon (void*) sock...??
 

Reply

Marsh Posté le 02-04-2004 à 00:09:09    

pourquoi tu cast ? si t'as besoin de caster, c'est que tu as un problème
 
int  pthread_create(pthread_t  *  thread,  pthread_attr_t * attr, void * (*start_routine)(void *),
       void * arg);

Reply

Marsh Posté le 02-04-2004 à 00:09:09   

Reply

Marsh Posté le 02-04-2004 à 15:45:28    

bon bon j'ai réussi avec les threads... mais maintenant, un autre pb!
Le serveur reçoit bien tout ce que les clients envoient, mais maintenant j'aimerais qu'il renvoi un message à tous les sockets connectés à lui même...
je pensais faire une boucle sur tous les sockets et faire un send à chaque fois, c'est la bonne méthode?

Reply

Marsh Posté le 02-04-2004 à 15:53:57    

C'est plus simple de le faire par thread, et puis c'est le même code.

Reply

Marsh Posté le 02-04-2004 à 17:34:56    

oui mais je voudrais envoyer le MEME message à tous... or les thread sont apparement indépendant? Comment faire communiquer des threads entre eux?

Reply

Marsh Posté le 02-04-2004 à 18:44:06    

Il doit falloir utiliser les Events pour ça, mais je n'en sais pas plus ...

Reply

Marsh Posté le 02-04-2004 à 21:22:52    

et tu crois pas qu'une boucle sur les sockets serait bien? le pb c'est que dans un thread je peux pas savoir quelles sont les connexions qui ont été ouvertes?
d'autres solutions?

Reply

Marsh Posté le 02-04-2004 à 21:36:28    

Sinon tu peux envoyer un message dans la structure passé au thread, mais tu n'auras aucun compte rendu

Reply

Marsh Posté le 02-04-2004 à 22:13:33    

hin?? comment ça?

Reply

Marsh Posté le 03-04-2004 à 09:12:09    

Et bien au lieu de ne passer que la variable sock à ton thread, tu passes un pointeur sur une structure, et dedans tu y mets ta variable socket et une variable message.
Et dans ta boucle de chaque thread tu lis cette variable et s'il y a qqchose tu traites, puis tu remets à 0 par example pour indiquer que c'est pris en compte.
Il faut utiliser les critical section pour éviter de lire/écrire en même temps et ça doit rouler.

Reply

Marsh Posté le 03-04-2004 à 14:43:06    

a ok... je vais voir ça! merci!

Reply

Marsh Posté le 03-04-2004 à 21:06:13    

une question de newb'... comment on passe plusieurs arguments de types différents à un thread?

Reply

Marsh Posté le 03-04-2004 à 21:10:16    

Passe un pointeur sur une structure !

Reply

Marsh Posté le 03-04-2004 à 21:27:08    

Cricri_ a écrit :

Passe un pointeur sur une structure !
 

mais il est ou le poste ou j'ai collé une exemple complet ?

Reply

Marsh Posté le 03-04-2004 à 21:36:13    

:pt1cable:  
Joker chef ..
je fais ce que je peux pour aider le monsieur, je n'ai pas d'autres prétentions ...
vi, l'est où le post ???  :ange:

Reply

Marsh Posté le 03-04-2004 à 21:49:07    

oh ben oui il est ou l'exemple? :d
 
bon sinon, j'ai un problème pour passer une structure en argument :(
dans mon proto j'ai
 
void ouverture_serveur(struct arg_serveur);
 
et à la compil', devc++ me mets
 
[Warning] `struct arg_serveur' declared inside parameter list
[Warning] its scope is only this definition or declaration, which is probably not what you want
 
...

Reply

Marsh Posté le 03-04-2004 à 21:56:43    

Reply

Marsh Posté le 03-04-2004 à 22:05:02    

ok merci je vais étudier ça!

Reply

Marsh Posté le 06-04-2004 à 01:15:44    

bon bon finalement après trop de galère, j'ai préféré faire une boucle sur mes sockets et ça roule!

Reply

Marsh Posté le 06-04-2004 à 01:53:11    

quand c'est terminé, mets à dispo le code complet stp

Reply

Marsh Posté le 06-04-2004 à 08:30:56    

Citation :

Sinon il faut utiliser select avec un time-out je pense, mais c'est moins pratique.


 
c'est bien plus pratique à mon avis  :love:

Reply

Marsh Posté le 06-04-2004 à 10:09:44    

ok je posterais ça dès que ça sera propre!

Reply

Marsh Posté le 08-04-2004 à 14:36:03    

Voilà mon code...
Me reste encore un pb... quand un tous les clients sont déco... le serveur part dans une boucle infinie sur le dernier message!

Code :
  1. #include<stdlib.h> 
  2. #include<unistd.h> 
  3. #include<stdio.h> 
  4. #include<winsock2.h>
  5. #include<io.h>
  6. #include<pthread.h>
  7. #include<sys/types.h>
  8. #define N 1000
  9. #define MAX 5
  10. void serveur();
  11. void client();
  12. void ouverture_client(SOCKET sock);
  13. void ouverture_serveur(SOCKET sock);
  14. SOCKET socks[MAX];
  15. int nb_connecte;
  16. main()
  17. {
  18. int c;
  19. printf("Que souhaitez vous lancer?\n1. Serveur\n2. Client\n" );
  20. scanf("%d",&c);
  21. if(c==1) serveur();
  22. if(c==2) client();
  23. }
  24. // Prog Serveur **************************************************
  25. void serveur()
  26. {
  27.     WSADATA wsa;
  28.     WSAStartup(MAKEWORD(2,0),&wsa);
  29.    
  30.     SOCKET server;       
  31.     SOCKET sock;
  32.     SOCKADDR_IN sinserv;   
  33.     SOCKADDR_IN sin;       
  34.     int port;
  35.    
  36.     printf("Port : " );
  37.     scanf("%i",&port);
  38.     sinserv.sin_family=AF_INET;
  39.     sinserv.sin_addr.s_addr=INADDR_ANY;
  40.     sinserv.sin_port=htons(port);
  41.     server=socket(AF_INET,SOCK_STREAM,0);
  42.    
  43.     bind(server,(SOCKADDR*)&sinserv,sizeof(sinserv));
  44.    
  45.     listen(server,0);
  46.     char buffer[N];
  47.     int sinsize;
  48.     int err=0;
  49.     pthread_t thread_serveur;
  50.    
  51.     while(1)
  52.     {
  53.         sinsize=sizeof(sin);
  54.         if((sock=accept(server,(SOCKADDR*)&sin,&sinsize))!=INVALID_SOCKET)
  55.         {
  56.         socks[nb_connecte]=sock;
  57.         pthread_create(&thread_serveur,  NULL, (void*)&ouverture_serveur,sock);
  58.         nb_connecte++;
  59.        
  60.         }
  61.     }
  62. }
  63. void ouverture_serveur(SOCKET sock)
  64. {
  65. int b;
  66. printf("Client Connecté\n" );
  67. char buffer[1000];
  68. while(1)
  69.     {
  70.     if(recv(sock,buffer,sizeof(buffer),0))
  71.         {
  72.         printf("Message reçu d'un client, le serveur traite l'info et envoi une réponse à tous les autres\n" );
  73.         for(b=0;b<nb_connecte;b++)
  74.                 {
  75.                 send(socks[b],buffer,sizeof(buffer),0);
  76.                 }
  77.         }
  78.     }
  79. }
  80. // Prog Client **************************************************
  81. void client()
  82. {
  83.     WSADATA wsa;
  84.     WSAStartup(MAKEWORD(2,0),&wsa);
  85.     SOCKET sock;   
  86.     SOCKADDR_IN sin;
  87.     printf("Ip : " );
  88.     char ip[15];   
  89.     scanf("%s",ip);
  90.    
  91.     printf("%s","\nPort : " );
  92.     int port; 
  93.     scanf("%i",&port);
  94.    
  95.     sin.sin_family=AF_INET;
  96.     sin.sin_addr.s_addr=inet_addr(ip);
  97.    
  98.     sin.sin_port=htons(port);
  99.    
  100.     sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  101.     bind(sock,(SOCKADDR*)&sin,sizeof(sin));
  102.     if(connect(sock,(SOCKADDR*)&sin,sizeof(sin)))
  103.     {
  104.         printf("La connection a echoue\n" );
  105.         system("PAUSE" );
  106.         exit(0);
  107.     }
  108.     char buffer[N];
  109.     int err=0;
  110.    
  111.     pthread_t thread_client;
  112.     pthread_create(&thread_client,  NULL, (void*)&ouverture_client,sock);
  113.    
  114.     while(1)
  115.     {
  116.         gets(buffer);
  117.         send(sock,buffer,sizeof(buffer),0);
  118.        
  119.     }
  120.     printf("Connection terminée\n\n" );
  121.     WSACleanup();
  122.     system("PAUSE" );
  123. }
  124. void ouverture_client(SOCKET sock)
  125. {
  126.     char buffer[N];
  127. while(1)
  128.     {
  129.     if(recv(sock,buffer,sizeof(buffer),0))
  130.         {
  131.         printf("Serveur > %s\n",buffer);
  132.         }
  133.     }
  134. }

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed