begin process at 2012 05 29 04:47:08
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C++ & C++ .NET

 > 

Windows

 > 

Réseau & Internet

 > 

fonction accepte bloquante..


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

fonction accepte bloquante..

mercredi 9 août 2006 à 23:46:20 | fonction accepte bloquante..

ssmint

Bonjour à tous,
nouveau problème de socket, côté server cette fois ci :
imaginons que plusieurs clients cherchent à se connecter sur le port d'écoute du server en même temps, 
je voudrais pouvoir recevoir toutes les connections puis choisir celle avec laquelle dialoguer...

=>Je fais donc un tableau de sock[] avec une boucle stoquant dans chaque sock les infos necessaires grâce à la fonction accept(), le problème, c'est que le socket server étant bloquant par défaut, la fonction accept() aussi..
Ce qui fait que la boucle bloque si il n'y a pas assez de conection entrantes. Dans mon code, j'ai pris 5 connections max mais s'il n'y en a que 2 ça ne marchepas , la boucle bloque sur la fonction accept()!!

=> Du coup, pas de problème : je rend donc le socket non bloquant grâce à la fonction ioctlsocket()!!

=> Sauf que du coup j'ai un autre problème lors de la communication avec le client, la fonction recv() n'est pas bloquante!
Alors c'est franchement chiant pour dialoguer, il faut mettre la fonction recv() dans une boucle infini pour recevoir un truc, compte tenu ds fonctionnalités que je veux mettre dans le prog, c'est impossible...


J'aimerais donc savoir si c'est possible de mettre une sorte de timeout sur la fonction accept() avec un socket bloquant ou "rerendre" le socket bloquant après avoir choisi le client (se que j'ai essayé mais qui ne marche pas)...

Voici mon code :

#include <stdio.h>
#include <winsock2.h>
#include <string.h>


int main()
{
// variables   
WSADATA wsa;
SOCKET server;    //Le socket qui servira à écouter sur un port
SOCKET sock[5];   //les sockets qui serviront à communiquer
SOCKADDR_IN sinserv; //parametres pour server
SOCKADDR_IN sin[5];  //parametres pour socks

char buffer[50], *P, *ip;
int sinsize;
int i=0, c,tmp;


     // Présentation :
                   
    system("color a");
    system("cls");
    system("TITLE TCP server by ssmint");

    // Mise en place de l'écoute : 
    
 WSAStartup(MAKEWORD(2,2),&wsa);
      
 sinserv.sin_family = AF_INET;         
 sinserv.sin_addr.s_addr = INADDR_ANY;    
 sinserv.sin_port=htons(1234);

 server = socket(AF_INET,SOCK_STREAM,0);
 bind(server,(SOCKADDR*)&sinserv,sizeof(sinserv));

 listen(server,5);
   
    // Socket rendu non bloquant : 
              
    u_long p=1;
    ioctlsocket(server, FIONBIO,&p);

    // Affichage connections et choix :
   
    printf("\nEcoute sur le port 1234. ..\t (3 sec)\n\n");
    Sleep(3000);//necessaire pour mettre connection en queue
    printf("Connexions recues :\t(5 max)\n");
    memset(buffer,sizeof(buffer),0);
    
    sinsize=sizeof(sin);
    while((sock[i]=accept(server,(SOCKADDR*)&sin[i],&sinsize))!=INVALID_SOCKET)
    {
           
            ip = inet_ntoa(sin[i].sin_addr);   //affichage ip client...
            printf("\n [%d]  %s ",i+1,ip);
            i++;
            
    }
        
      // Pas de connections :
              
        if(sock[0]==INVALID_SOCKET)
        {
              printf("\n\tAucune\n\n");
              system("pause");
              WSACleanup();
              exit(0);
        }
       
        // Choix de la connection pour dialogue :
                
        printf("\n=> Selection connection: ");
        scanf("%d", &c);
        c--;
       
        // Fermeture des sockets inutilisés :
                    
        for(i=0; i<5; i++)
        {
                 if(i!=c)
                 {
                            closesocket(sock[i]);
                 }
        }

        p=0;                                 // NE FONCTIONNE PAS!!!
        ioctlsocket(server, FIONBIO,&p);     //une fois la fonction accept() passé
                                             //le socket server reste non-bloquant
system("pause");
}

Merci d'avance désolé pour le "pavé".

 

jeudi 10 août 2006 à 06:41:38 | Re : fonction accepte bloquante..

nightlord666

Membre Club
Pour ça, tu met ta boucle infinie avec recv dans un thread que tu aura créé. Regarde sur developpez.com, il y a un article sur les serveurs multithreads.


Sachant qu'on peut toujours enlever une ligne à un programme, et que dans un programme il y a toujours un bug, un programme peut se résumer à une ligne avec un bug.
jeudi 10 août 2006 à 09:52:07 | Re : fonction accepte bloquante..

turnerom

				Re,
il faut que tu utilise la fonction select, voici un exemple de code qui marche (version Linux par contre mais l'idée est la, c'est + ou - la meme chose sous WinWin)
Ce code permet a nombre illimité (enfin presque 64511 pour etre precis) de client de se connecter, et lui envoi le fichier passer en paramètre.



int
main ( int argc, char*argv[])
{

intds,port,ta,da,sock;
structsockaddr_inname;

if(argc!=2)/* Test Le nombre d'arguments */
{
fprintf(stderr,"Usage : ./serveur port \n");
exit(0);
}

puts("Serveur en attente");/*Message d'attente*/
puts("");

port=atoi(argv[1]);/*L'argument 1 est le numero de port sur lequel le serveur attend*/

ds=socket(PF_INET, SOCK_STREAM, 0);/*On crée notre socket de connection*/

if(ds<0)/*Avec un test pour éviter les erreurs*/
{
perror("Probleme socket : ");
exit(-1);
}

init_sockaddr(&name,"0.0.0.0",port);/*On initialise notre socket internet, le port ecoute sur toute les adresse*/

if(bind(ds, (structsockaddr*)&name, sizeof(structsockaddr))<0)/*On bind*/
{/*Avec un test pour éviter les erreurs*/
perror("Probleme bind : ");
exit(-1);
}

if(listen(ds, FILED)<0)/*On listen dans notre socket de connexion jusqu'à "FILED" client max*/
{/*Avec un test pour éviter les erreurs*/
perror("Probleme listen ");
exit(-2);
}

while(1)/*Serveur multi-client donc boucle infinie*/
{

FD_ZERO(listeClients);/*On reinitialise notre liste d'attente*/
FD_SET(ds,listeClients);/*Dans laquelle on place notre socket de connexion*/

if((select(FILED+1, listeClients, NULL, NULL,NULL))<0)/*On fait notre select sur notre liste de client*/
{/*Avec un test pour éviter les erreurs*/
perror("select");
exit(-3);
}

for(sock=3;sock<FILED;sock++)/*On parcourt toutes nos (potentielles) sockets*/
{

if(FD_ISSET(sock,listeClients))/*On regarde quelle descripteur change d'etat*/
{
if(sock==ds)/*Si c'est la socket de connection...*/
{
da=accept(ds, (structsockaddr*)&name, &ta);/*...on l'accepte...*/
if(da<0)/*...toujours avec un test pour éviter les erreurs...*/
{
perror("Probleme accept ");
exit(-3);
}
printf("Connexion socket n°%d établie\n",da);
FD_SET(da,listeClients);/*...et on la rajoute dans notre liste de clients*/
}
elsetraiterClient(sock);/*Si ce n'est pas la socket de connection, c'est alors une socket de data*/
/*On appelle donc notre fonction de transfert proprement dite en passant en argument...*/
}/*...la socket où le client envoi son fichier*/
}

}

close(da);
close(ds);

return0;
}


voidinit_sockaddr(structsockaddr_in*name, constchar*hostname, uint16_tport)
{
structhostent*hostinfo;


name->sin_family=AF_INET;/* Adresses IPV4 (Internet) */
name->sin_port=htons(port);/* On gère le little/big Endian */

hostinfo=gethostbyname(hostname);/* appeler les fonctions de résolution de nom de la libC */

if(hostinfo==NULL)/* Si ne peut transformer le nom de la machine en adresse IP */
{
fprintf(stderr, "Unknown host %s.\n", hostname);
exit(-1);
}
name->sin_addr=*(structin_addr*)hostinfo->h_addr;/* Le dernier champs de la structure est garni */
}

voidtraiterClient(intda)
{
charbuffer[SIZE],nomFich[SIZE];
intfich;
ssize_tsize;

if(read(da,nomFich,SIZE)<0)/*On récupere le nom du fichier*/
{/*Avec toujours un petit test pour éviter les erreurs*/
perror("Nom de fichier non recu : ");
exit(-4);
}

if(nomFich==NULL)/*Avec meme un 2eme test pour être totalement sûr*/
{
perror("Nom de fichier invalide");
exit(-5);
}

/*Si tout es bon...*/
fich=open(nomFich,O_WRONLY|O_CREAT,777/*,S_IRWXU|S_IRWXG|S_IRWXO*/);/*On ouvre le fichier (ou on le cree s'il n'existe pas) en lecture seule avec le nom recu*/
/* voir (1) en bas de page*/
puts("Réception en cours...");

while((size=read(da,buffer,SIZE)))write(fich,buffer,size);/*Tant que c'est pas la fin du fichier on lit dans la socket et on ecrit dans le fichier*/

puts("Réception terminée");
puts("");

close(da);/*On ferme la socket...*/
close(fich);/*...et le fichier*/

}


TuRn3r
jeudi 9 septembre 2010 à 15:05:33 | Re : fonction accepte bloquante..

ZapaN28

ssmint a dit :
"je rend donc le socket non bloquant grâce à la fonction ioctlsocket()!"

merci je connaissais pas ! ca va m'aider nikel

Zap ;)


Cette discussion est classée dans : fonction, server, socket, sin, sock


Répondre à ce message

Sujets en rapport avec ce message

Probleme sockets de mer** [ par zzzzzz ] bé je suis plus quoi faire j'en suis toujours au meme prob y'en a 1 qui me dit d'utiliser strstr() l'autre strcmp() fin bref ca serrais sympas si quel Probleme de Client Serveur [ par Krox68 ] voila jaimerais faire un programme client qui puisse se connecter a ce serveur : #include void main(){ WSADATA WSAData; WSAStartup(MAKEWORD(2,0), &WS LERREUR QUI TUE §§§§§§§§§§§§§§§§ [ par Avalon10101 ] Vla jai fé mon prog tout é juste mais ya une erreur que je narrive vraiment pas à comprendre ! :C:\Documents and Settings\Alex\Mes documents\Makefile. pb socket [ par surfeurnet ] voici mon programme qui a pour l'instant pour unique but de se connecter à un serveur :# include # include # pragma comment (lib,"w32_32.lib")char ip, prob sock [ par epoc ] voilà, g commencé la prog des socks en vc++, mais rien ne transitte alors que la connexion semble être bien effectuée, voilà le code :**************** [SOCKET]Tjrs le pb de recuperation du buffer recv() [ par enthaz ] Allez J me lance : ca fait des heures et des heures ke le newb ke je suischerche la solution :D un coté j ai un logiciel client ki envoie "coucou" sur Socket, quand tu nous tiens ... [ par enthaz ] Allez J me lance : ca fait des heures et des heures ke le newb ke je suischerche la solution :D un coté j ai un logiciel client ki envoie "coucou" sur Pb de socket 'winsock2.h' [ par amodels ] Bonjour tlm.Je voudrais éxécuter l'adresse http://127.0.0.1/toto.php avec ce code :#include #include #pragma comment(lib, "ws2_32.lib")void main(){WS PROB SOCKETS CON [ par zzzzzz ] le code source marche mais quand je rajoute un cout#include #pragma comment(lib,"ws2_32.lib")#include int main(void) erreur 10038 [ par made_in_france ] Hello ! j'ai un probleme avec la fonction bind de mon programme. En effet cette fonction me renvois l'erreur 10038 « attempted ». Est ce que quelqu'un


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,733 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales