[socket] select() ou fork()?

select() ou fork()? [socket] - C++ - Programmation

Marsh Posté le 27-04-2005 à 09:24:49    

Bonjour!
 
Je développe un serveur communiquant par sockets TCP dont la contrainte principale est d'être portable sous linux et sous windows.
Ce serveur doit accepter plusieurs connexions (et réception de message) simultanées. Pour gérer cela, j'hésitais entre le classique fork et un select(). J'ai finalement implémenté ce serveur multi-clients avec un select() et les macros FD_SET, FD_ISSET...
Les connexions et les échanges de messages fonctionnent correctement en simultané, mais j'ai quand même un problème. Mon programme s'enmêle les pinceaux avec les IP des clients!! :??:  
 
J'ai créé une classe Masocket, ce qui permet d'éclaircir le code et de gérer la portabilité de manière transparente. Je déclare 1 objet Masocket correspondant au listener et un tableau contenant les objets Masocket correspondant au clients. Dans les exemples de code que j'ai pu trouver pour illuster l'utilisation du select(), les sockets sont toujours des int (unix).
Pour que ce soit plus clair, voici mon code :

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "Masocket.h"
  4. #ifdef _WIN32
  5. #include <winsock2.h>
  6. #pragma  comment(lib,"ws2_32.lib" )
  7. #else
  8. #include <unistd.h>
  9. #include <sys/socket.h>
  10. #include <sys/types.h>
  11. #include <netinet/in.h>
  12. #include <arpa/inet.h>
  13. typedef struct sockaddr_in SOCKADDR_IN;
  14. #endif
  15. #define PORT 3490
  16. #define MAXMSG 255
  17. Masocket clist [5];
  18. Masocket listener = Socketiam();
  19. fd_set master;
  20. fd_set temp;
  21. int fdmax;
  22. int i;
  23. void read_socks(){
  24. int listnum, client,newclient;
  25. bool loadsock=false;
  26. bool findsock=false;
  27. // run through the existing connections looking for data to read
  28.             for(i = 0; i <= fdmax; i++) {
  29.                 if (FD_ISSET(i,&temp)) {
  30.                     if (i == listener.getSock()) { //handle new connections
  31.   for (listnum = 0; listnum < 5 && (!loadsock); listnum++) {
  32.   if (clist[listnum].getSock()==0) {
  33.    newclient=listnum;
  34.    loadsock=true;
  35.   }
  36.  }
  37.  if (listener.acceptSock(clist[newclient])) {
  38. FD_SET(clist[newclient].getSock(),&master); // add to master set
  39. if (clist[newclient].getSock() > fdmax) {    // keep track of the maximum
  40. fdmax = clist[newclient].getSock();
  41. }
  42. printf("Got connection from \n",inet_ntoa(clist[newclient].getClientAddr().sin_addr));
  43. }
  44. }
  45. else { // handle data from a client
  46. for (listnum = 0; listnum < 5 && (!findsock); listnum++) {
  47. if (clist[listnum].getSock()==i) {
  48.      client=listnum;
  49.      findsock=true;
  50. }
  51. }
  52. if (clist[client].receive()==-1){
  53. printf(inet_ntoa(clist[client].getClientAddr().sin_addr));
  54. printf(" deconnect\r\n" );
  55. clist[client].kill(2);
  56. clist[client].closeSock();
  57. FD_CLR(i, &master); // remove from master set
  58. }
  59. }
  60. } // if
  61. } //for
  62. }
  63. void main(){
  64. int readsocks;      /* Number of sockets ready for reading */
  65. printf("Serveur demarre...\r\n" );
  66. listener.initSock(PORT,"" );
  67. listener.initServer(10);
  68. FD_ZERO(&master);
  69. FD_ZERO(&temp);
  70. listener.setinFD(master);
  71. fdmax = listener.getSock();
  72. while(TRUE)
  73. {
  74.  temp = master; // copy the master fd_set
  75.  readsocks =select(0, &temp, NULL, NULL, NULL);
  76.         if (readsocks < 0) {
  77.   perror("select" );
  78.   exit(EXIT_FAILURE);
  79.  }
  80.  if (readsocks == 0) {
  81.   printf("." );
  82.   fflush(stdout);
  83.  } else read_socks();
  84. }//while
  85. listener.closeSock();
  86. #ifdef _WIN32
  87. WSACleanup();
  88. #endif
  89. }


 
Concrètement, ma question est la suivante :  
Le fait que je manipule des objets non primitifs est-il un problème pour une gestion multi-clients avec select() ou ce problème peut-il être résolu? Est-ce fork() la solution pour conserver ma classe Masocket?
 
Question subsidiaire :  
Suis-je obligée de faire un tableau de Masocket? ou bien 1 Masocket pour le listener et 1 Masocket pour le client courant pourraient suffire?
Merci d'avance pour votre aide!

Reply

Marsh Posté le 27-04-2005 à 09:24:49   

Reply

Marsh Posté le 04-05-2005 à 11:52:14    

J'ai finalement résolu mon problème toute seule, merci pour votre aide! Vraiment très concluant de poster sur ce forum!!
L'embrouille au niveau des adresses IP des clients n'était en fait qu'une illusion. Le serveur fonctionnait correctement. C'est l'appel à inet_noa() qui conserve la dernière adresse..
Sinon, j'ai changé la structure de stockage de mes sockets pour une map.

Code :
  1. #include <map>
  2. std::map <int,Masocket> clientsmap;


 
En espérant que ce sujet, aide quelqu'un à défaut de m'avoir aidé moi!
 

Reply

Sujets relatifs:

Leave a Replay

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