mellie35 | 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 :
- #include <stdio.h>
- #include <string.h>
- #include "Masocket.h"
- #ifdef _WIN32
- #include <winsock2.h>
- #pragma comment(lib,"ws2_32.lib" )
- #else
- #include <unistd.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- typedef struct sockaddr_in SOCKADDR_IN;
- #endif
- #define PORT 3490
- #define MAXMSG 255
- Masocket clist [5];
- Masocket listener = Socketiam();
- fd_set master;
- fd_set temp;
- int fdmax;
- int i;
- void read_socks(){
- int listnum, client,newclient;
- bool loadsock=false;
- bool findsock=false;
- // run through the existing connections looking for data to read
- for(i = 0; i <= fdmax; i++) {
- if (FD_ISSET(i,&temp)) {
- if (i == listener.getSock()) { //handle new connections
- for (listnum = 0; listnum < 5 && (!loadsock); listnum++) {
- if (clist[listnum].getSock()==0) {
- newclient=listnum;
- loadsock=true;
- }
- }
- if (listener.acceptSock(clist[newclient])) {
- FD_SET(clist[newclient].getSock(),&master); // add to master set
- if (clist[newclient].getSock() > fdmax) { // keep track of the maximum
- fdmax = clist[newclient].getSock();
- }
- printf("Got connection from \n",inet_ntoa(clist[newclient].getClientAddr().sin_addr));
- }
- }
- else { // handle data from a client
- for (listnum = 0; listnum < 5 && (!findsock); listnum++) {
- if (clist[listnum].getSock()==i) {
- client=listnum;
- findsock=true;
- }
- }
- if (clist[client].receive()==-1){
- printf(inet_ntoa(clist[client].getClientAddr().sin_addr));
- printf(" deconnect\r\n" );
- clist[client].kill(2);
- clist[client].closeSock();
- FD_CLR(i, &master); // remove from master set
- }
- }
- } // if
- } //for
- }
- void main(){
- int readsocks; /* Number of sockets ready for reading */
- printf("Serveur demarre...\r\n" );
- listener.initSock(PORT,"" );
- listener.initServer(10);
- FD_ZERO(&master);
- FD_ZERO(&temp);
- listener.setinFD(master);
- fdmax = listener.getSock();
- while(TRUE)
- {
- temp = master; // copy the master fd_set
- readsocks =select(0, &temp, NULL, NULL, NULL);
- if (readsocks < 0) {
- perror("select" );
- exit(EXIT_FAILURE);
- }
- if (readsocks == 0) {
- printf("." );
- fflush(stdout);
- } else read_socks();
- }//while
- listener.closeSock();
- #ifdef _WIN32
- WSACleanup();
- #endif
- }
|
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! |