Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
671 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [Débutant] Socket

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Débutant] Socket

n°1304700
casafa
Posté le 13-02-2006 à 19:36:37  profilanswer
 

Bonjour,
 
J'esseye de faire un script qui vérifie si un proxy fonctionne, voici mon code:
 

Code :
  1. #include <iostream>
  2. #include <winsock2.h>
  3. #pragma comment(lib, "ws2_32.lib" )
  4. using namespace std;
  5. int main(){
  6. WSADATA WSAData;
  7. WSAStartup(MAKEWORD(2,0), &WSAData);
  8. SOCKET sock;
  9. SOCKADDR_IN sin;
  10. sin.sin_addr.s_addr = inet_addr("81.242.92.251" );
  11. sin.sin_family  = AF_INET;
  12. sin.sin_port  = htons(80);
  13. sock = socket(AF_INET,SOCK_STREAM,0);
  14. bind(sock, (SOCKADDR *)&sin, sizeof(sin));
  15. if (connect(sock, (SOCKADDR *)&sin, sizeof(sin))==-1)
  16. {
  17.  cout<<"Mauvais proxy"<<endl;
  18. }else
  19. {
  20.  cout<<"Bon proxy"<<endl;
  21. }
  22. WSACleanup();
  23. return 0;
  24. }


 
Mes 2 questions:
1) Quand le proxy ne fonctionne pas, il faut environ 20 secondes avant qu'il me dise : "Mauvais proxy" : il y a t'il moyen de mettre une limite de temps et quel limite de temps me conseilleriez-vous pour tester un proxy ?
2) Y a-til moyen de rendre ce code compatible avec Linux sans changer trop de chose dans le code source ?
 
Merci d'avance...

mood
Publicité
Posté le 13-02-2006 à 19:36:37  profilanswer
 

n°1305701
bigears
Posté le 14-02-2006 à 23:59:49  profilanswer
 

1) sous linux j'utiliserai les signaux, avec SIGALARM
 
2) c'est quasi identique, juste les structures et 1 ou 2 fonction changent(c dans sys/socket.h je crois )

n°1307334
casafa
Posté le 16-02-2006 à 17:06:33  profilanswer
 

Merci de ta réponse mais existe t-il quelque chose de similaire à sigalarm sous Windows ?

n°1307425
bigears
Posté le 16-02-2006 à 19:08:51  profilanswer
 

alors la, aucune idée.
 
Mais je pense plutot qu'au bout de 20 secondes, il recoit une réponse du proxy qui dit qu'il ne possede pas de service sur le port 80.
 
Regarde les trames que tu recoit avec ethereal, tu saura d'ou vient l'attente.

n°1307426
casafa
Posté le 16-02-2006 à 19:18:46  profilanswer
 

Peu importe d'où vient le problème de temps : je veux juste trouver un truc qui permet de stopper la fonction "connect" après x seconde.

n°1307564
fat
Posté le 17-02-2006 à 00:19:39  profilanswer
 

utilise une socket non bloquante
tu crée une socket, tu la rends non bloquante avec fcntl, tu la connecte avec connect, si connect te retourne EINPROGRESS, tu utilises alors un select pour savoir si elle est connecté, tu peux préciser le timeout dans le select
 
tu trouvera une explication plus détaillée ici :
http://www.faqs.org/faqs/unix-faq/socket/


Message édité par fat le 17-02-2006 à 00:20:00
n°1310967
casafa
Posté le 21-02-2006 à 20:21:33  profilanswer
 

Merci (avec en peu de retard) de ta réponse.
 
Je vien d'esseyer de comprendre en peu ce que faisait fcntl mais j'ai un petit problème lors de la compilation de mon programme sous windows:

Code :
  1. #include <iostream>
  2. #include <winsock2.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>
  5. #pragma comment(lib, "ws2_32.lib" )
  6. using namespace std;
  7. int main(){
  8. ....
  9. sock = socket(AF_INET,SOCK_STREAM,0);
  10. fcntl (sock, F_SETFL, O_NONBLOCK);
  11. }


 
Et les erreurs:
proxy.cpp: In function `int main()':
proxy.cpp:18: error: `F_SETFL' undeclared (first use this function)
proxy.cpp:18: error: (Each undeclared identifier is reported only once for each function it appears in.)
proxy.cpp:18: error: `O_NONBLOCK' undeclared (first use this function)
proxy.cpp:18: error: `fcntl' undeclared (first use this function)
 
 
Merci d'avance...


Message édité par casafa le 21-02-2006 à 20:28:06
n°1310989
nargy
Posté le 21-02-2006 à 20:53:32  profilanswer
 

Avec linux:
WSADATA et fonctions relatives n existent pas,
 
SOCKADDR s appelle:
struct sockaddr
 
SOCKADDR_IN s appelle:
struct sockaddr_in *
 
Pour `F_SETFL' et `O_NONBLOCK':
essaye les includes:
<sys/fcntl.h>
<sys/ioctl.h>
<sys/types.h>
<sys/stat.h>
Il est aussi possible sur ton système que O_NONBLOCK s appelle O_NDELAY (ancien nom).

n°1311033
casafa
Posté le 21-02-2006 à 22:00:32  profilanswer
 

Merci de ta réponse mais.....dans mon deuxième message, je dit que je cherche quelque chose qui permet de ne pas attendre 20 seconde pour que mon programme m'affiche "mauvais proxy" pour WINDOWS...
-On m'a proposer la solution de SIGALARM mais apparment c'est compatible que Linux.
-Maintenant on me propose un socket non-bloquant encore pour Linux.
 
Avez-vous une solution compatible Windows/linux ?
 
Ha la la si tout le monde serait sur Linux, la vie des programmeurs seraient bien plus simple, lol

n°1311129
blastman
just me !
Posté le 22-02-2006 à 05:55:29  profilanswer
 

je vais être légérement hors sujet mais,
 
aurais tu des liens intéressants sur les sockets ?


---------------
http://www.blastmanu.info
mood
Publicité
Posté le 22-02-2006 à 05:55:29  profilanswer
 

n°1311133
el muchach​o
Comfortably Numb
Posté le 22-02-2006 à 06:12:46  profilanswer
 

blast, va voir sur le site perso de Sve@r, il a écrit des docs très utiles, mais je ne sais pas si les winsocks fonctionnent de la même manière, rien n'est moins sûr.


Message édité par el muchacho le 22-02-2006 à 06:17:08
n°1311160
blastman
just me !
Posté le 22-02-2006 à 09:06:29  profilanswer
 

ok merci


---------------
http://www.blastmanu.info
n°1312466
casafa
Posté le 23-02-2006 à 17:03:34  profilanswer
 

Personne n'a de solution ? :(

n°1312491
nargy
Posté le 23-02-2006 à 17:33:18  profilanswer
 

La dernière fois que j ai fait une socket sous windoz, ça date! tu peut toujours aller voir du côté du site de krosoft.
 
Sous linux man 7 socket mentionne:
SO_RCVTIMEO/SO_SNDTIMEO (timeout),
SO_RCVLOWAT/SO_SNDLOWAT (buffer mémoire),
SO_SNDBUF/SO_RCVBUF (buffer socket)
 
Vaguement relatif:
SO_LINGER (timeout fermeture)
SO_PRIORITY (priorité IP)
 
Ioctls:
SIOCGSTAMP (timestamp du dernier octet reçu)
 
Si tu trouve pas mais que ton code marche sous linux, tu peut toujours essayer d installer Cygwin (émulateur+compilateur linux sous windoz).
 

n°1312570
casafa
Posté le 23-02-2006 à 19:01:21  profilanswer
 

Je ne suis pas très interresser par le solution de Cygwin surtout si je veut distribuer mon programme !!
Avez-vous une solution compatible windows/linux ? je commence a désespérer :(

n°1312682
casafa
Posté le 23-02-2006 à 21:58:31  profilanswer
 

Je viens de trouver une fonction similaire à fctnl mais pour windows:
 

Code :
  1. int main(){
  2. fd_set readfds;
  3. struct timeval tv;
  4.         tv.tv_sec = 2;
  5.         tv.tv_usec = 500000;
  6. int nonblocking=0;
  7. WSADATA WSAData;
  8. WSAStartup(MAKEWORD(2,0), &WSAData);
  9. SOCKET sock;
  10. SOCKADDR_IN sin;
  11. sin.sin_addr.s_addr = inet_addr("213.121.209.15" );
  12. sin.sin_family  = AF_INET;
  13. sin.sin_port  = htons(80);
  14. sock = socket(AF_INET,SOCK_STREAM,0);
  15. bind(sock, (SOCKADDR *)&sin, sizeof(sin));
  16. //fcntl (sock, F_SETFL, O_NONBLOCK);         /* LINUX */
  17. ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);  /* WINDOWS */
  18. connect(sock, (SOCKADDR *)&sin, sizeof(sin));
  19. select(sock, &readfds, NULL, NULL, &tv);
  20. WSACleanup();
  21. return 0;
  22. }


 
Le problème c'est que la fonction "connect" bloque quand même mon programme pendant 20 secondes comme si mon socket n'était pas non-bloquant !

n°1312699
nargy
Posté le 23-02-2006 à 22:23:58  profilanswer
 

Quelques suggestions:
 
Sur un vieux code linux que j ai retrouvé, j utilise inet_aton plûtot que inet_addr:

Code :
  1. struct sockaddr_in addr;
  2.   addr.sin_family=AF_INET;
  3.   addr.sin_port=port;
  4.   if (!inet_aton((const char*)hostip,&addr.sin_addr))
  5.     addr.sin_addr.s_addr=0; // error!


 
D après man inet_addr:

Citation :


This is an obsolete interface to inet_aton


 
Autre chose: vérifie les appels à bind, connect et select?

n°1312701
nargy
Posté le 23-02-2006 à 22:25:38  profilanswer
 

Il y a la fonction perror(NULL); qui affiche la dernière erreure système survenue.

n°1312707
casafa
Posté le 23-02-2006 à 22:39:41  profilanswer
 

1) Apparament inet_aton n'existe pas sur windows !
 
2) Je vien de vérifier l'appel de "bind":

Code :
  1. if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))){
  2.  cout<<"Erreur 1"<<endl;
  3.  exit(0);
  4. }


 
Et lors de l'éxécution du programme il m'affiche "Erreur 1", pourquoi ?

n°1312731
nargy
Posté le 23-02-2006 à 23:36:37  profilanswer
 

essaye plutot:
(include stdio.h)

Code :
  1. if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))){
  2.               perror(NULL);
  3.               exit(0);
  4.           }


 
... pour avoir une description de l erreure.

n°1312733
nargy
Posté le 23-02-2006 à 23:37:37  profilanswer
 

sous linux, inet_aton est quelque part dans:
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

n°1312743
nargy
Posté le 23-02-2006 à 23:43:35  profilanswer
 

quelques erreures possibles:
 
*       EBADF  sockfd is not a valid descriptor.
*       EACCES The address is protected, and the user is not the super-user.
*       EINVAL The socket is already bound to an address.

n°1313090
casafa
Posté le 24-02-2006 à 15:32:47  profilanswer
 

Merci pour toutes vos réponses, voici comment j'ai fait:
 

Code :
  1. sock = socket(AF_INET,SOCK_STREAM,0);
  2. if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))==EBADF){
  3.  cout<<"EBADF\n"<<endl;
  4.  exit(0);
  5. }else if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))==EACCES){
  6.  cout<<"EACCES\n"<<endl;
  7.  exit(0);
  8. }else if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))==EINVAL){
  9.  cout<<"EINVAL\n"<<endl;
  10.  exit(0);
  11. }
  12. //fcntl (sock, F_SETFL, O_NONBLOCK);         /* LINUX */
  13. ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);  /* WINDOWS */
  14. if(connect(sock, (SOCKADDR *)&sin, sizeof(sin))==-1){
  15.  cout<<"Erreur 2: "<<endl;
  16.  perror(NULL);
  17.  exit(0);
  18. }
  19. if(select(sock, &readfds, NULL, NULL, &tv) == SOCKET_ERROR){
  20.  cout<<"Erreur 3: "<<endl;
  21.  perror(NULL);
  22.  exit(0);
  23. }
  24. cout<<"Le proxy fonctionne.\n";


 
1) Si je teste mon programme sur une ip qui n'est pas un proxy, j'ai le droit à ce message 20 secondes après l'éxécution:
$ ./proxy.exe  
Erreur 2:  
No error
==> Pourquoi lui faut-il 20 secondes avant de m'afficher "Erreur 2.." alors que j'ai un socket non-bloquant ?
 
2) Si je teste mon programme sur une ip qui est un proxy:
$ ./proxy.exe  
Erreur 3:  
No error
==> Pourquoi m'affiche t'il cette erreur ?!
 
Autre petite question : Il me semble que windows (contrairement à Linux) n'est pas très évolué pour la programmation de socket, non ? Est-ce normal ? !
 
Merci d'avance...

n°1313122
nargy
Posté le 24-02-2006 à 16:08:23  profilanswer
 

OOps, tu n est pas habitué à programmer en C...
 
La dernière erreure système se situe dans la variable <<errno>> (include errno.h). Chaque appel système met une valeur dans cette variable, soit 0 si pas d erreure, soit un numéro d erreure. L appel système retourne toujours -1 en cas d erreure.
 
Donc, d une part, ce n est pas le retour d un appel système qu il faut tester pour connaitre l erreure, mais la variable errno. En cas d erreure le retour sera -1 et errno contient le code d erreure.
 
Dautre part, lorsque tu écrit quelquechose à l aide de cout<<blabla<<endl;, celà change le code d erreure contenu dans errno, car cela fait appel au système. Dans ton cas il a réussi à écrire <<Erreure2:>> donc tout s est bien passé, donc pas d erreure.
 
Ok, le plus simple, je réécris le programme, fais du copier/coller:
 

Code :
  1. if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))<0){
  2.         perror("L ouverture de socket a foiré car" );
  3.         exit(1);
  4.     }
  5. /* LINUX: */
  6.     //fcntl (sock, F_SETFL, O_NONBLOCK);                                     
  7. /* WINDOWS: */
  8.   if(ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking)<0){
  9.         perror("La socket ne peut être rendu non-bloquante car" );
  10.         cerr<<"On continue quand même avec socket bloquante. Patience."<<endl;
  11.     }
  12.     if(connect(sock, (SOCKADDR *)&sin, sizeof(sin))<0){
  13.         perror("La connexion à l hôte distant a foiré car" );
  14.         exit(1);
  15.     }
  16.     int r=select(sock, &readfds, NULL, NULL, &tv);
  17.     if(r<0){
  18.         perror("La réponse de connexion a foiré car" );
  19.         exit(1);
  20.     }
  21.     else if(r==0){
  22.         cerr<<"Le proxy ne semble pas en route."<<endl;
  23.         exit(1);
  24.     }
  25.     else
  26.         cout<<"Le proxy a répondu favorablement. Tout semble ok."<<endl;


 
 
 
 

n°1313133
casafa
Posté le 24-02-2006 à 16:28:41  profilanswer
 

Merci pour cette correction d'erreurs mais quelques soit l'ip, j'ai le droit au message suivant:
$ ./proxy.exe  
L ouverture de socket a foiré car: No error

n°1313152
nargy
Posté le 24-02-2006 à 17:03:43  profilanswer
 

inclus <errno.h> et teste la variable errno avec les valeurs:
EPROTONOSUPPORT: protocole non supporté
EAFNOSUPPORT: famille non supporté
ENFILE: plus sockets libres
EMFILE: plus de fichiers libres
EACCES: accès interdit à ce type/protocol
ENOBUFS: plus de mémoire
ENOMEM: plus de mémoire
EINVAL: protocole ou famille inconnu

n°1313153
nargy
Posté le 24-02-2006 à 17:04:13  profilanswer
 

Note: testes la avant perror()

n°1313162
casafa
Posté le 24-02-2006 à 17:21:35  profilanswer
 

Voici ma fonctions erreurs:
 

Code :
  1. void erreurs(int erreur){
  2. switch(erreur){
  3.  case ENFILE:
  4.   cerr<<"plus sockets libres"<<endl;
  5.   exit(1);
  6.  case EMFILE:
  7.   cerr<<"plus de fichiers libres"<<endl;
  8.   exit(1);
  9.  case EACCES:
  10.   cerr<<"accès interdit à ce type/protocol "<<endl;
  11.   exit(1);
  12.  case ENOMEM:
  13.   cerr<<"plus de mémoire"<<endl;
  14.   exit(1);
  15.  case EINVAL:
  16.   cerr<<"protocole ou famille inconnu"<<endl;
  17.   exit(1);
  18.  default:
  19.   cout<<"Pas d'erreur"<<endl;
  20. }
  21. return ;
  22. }


 
Si j'appelle ma fonction erreurs(errno); avant ou après la fonction "bind" il m'affiche toujours : "Pas d'erreur".
Par contre EPROTONOSUPPORT, EAFNOSUPPORT et ENOBUFS ne semble pas exister sur windows !


Message édité par casafa le 24-02-2006 à 17:23:41
n°1313195
nargy
Posté le 24-02-2006 à 18:45:03  profilanswer
 

Ok, mais teste aussi:
case 0: // pas d erreure
default: // erreure inconnue, afficher le numéro d erreure
 

n°1313196
nargy
Posté le 24-02-2006 à 18:46:35  profilanswer
 

cerr<<"Erreure inconnue de numéro:"<<erreur<<endl;

n°1313201
casafa
Posté le 24-02-2006 à 19:04:05  profilanswer
 

J'ai refait la fonction:
 

Code :
  1. void erreurs(int erreur){
  2. switch(erreur){
  3.  case 0:
  4.   cout<<"Pas d'erreur"<<endl;
  5.   break;
  6.  case ENFILE:
  7.   cerr<<"plus sockets libres"<<endl;
  8.   exit(1);
  9.  case EMFILE:
  10.   cerr<<"plus de fichiers libres"<<endl;
  11.   exit(1);
  12.  case EACCES:
  13.   cerr<<"accès interdit à ce type/protocol "<<endl;
  14.   exit(1);
  15.  case ENOMEM:
  16.   cerr<<"plus de mémoire"<<endl;
  17.   exit(1);
  18.  case EINVAL:
  19.   cerr<<"protocole ou famille inconnu"<<endl;
  20.   exit(1);
  21.  default:
  22.   cerr<<"Erreure inconnue de numéro:"<<erreur<<endl;
  23. }
  24. return ;
  25. }


 
Et voici le bout de code:

Code :
  1. erreurs(errno);
  2. if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))<0){
  3.         perror("L ouverture de socket a foiré car" );
  4.         exit(1);
  5. }


 
Et voici le résultat spectaculaire que j'ai su produire  :wahoo: :
$ ./proxy.exe  
Pas d'erreur
L ouverture de socket a foiré car: No error
 
 
Qu'est ce que j'ai encore fait comme bétise ?


Message édité par casafa le 24-02-2006 à 19:05:13
n°1313216
nargy
Posté le 24-02-2006 à 19:39:25  profilanswer
 

[code]
    if(bind(sock, (SOCKADDR *)&sin, sizeof(sin))<0){
           erreurs(errno);
           exit(1);
    }  
[/quote]

n°1313348
casafa
Posté le 24-02-2006 à 23:37:26  profilanswer
 

Même en mettant le "erreurs(errorno);" après le bind, j'ai le même message : "Pas d'erreur".

n°1313544
casafa
Posté le 25-02-2006 à 17:14:44  profilanswer
 

J'ai su afficher le numéro de l'erreur avec  : WSAGetLastError().
Le numéro de l'erreur est : 10049 : mais qu'est ce que ça signifie ?
 
[edit]
10049 ==> Impossible d'allouer l'adresse demandée.
J'ai cette erreur avec toutes les ips sauf 127.0.0.1 et 192.168.0.2 (celle de mon pc où j'éxécute mon programme), pourquoi ai-je une erreur 10049 avec les autres ip ?
[edit]


Message édité par casafa le 25-02-2006 à 17:28:08
n°1313618
casafa
Posté le 25-02-2006 à 20:14:13  profilanswer
 

Après une longue recherche sur google:j'ai trouvé un post en anglais qui disait qu'il ne fallait pas utiliser bind pour un programme client (si j'ai bien compris pcq moi et l'anglais...) : http://www.codeguru.com/forum/show [...] did=259574 !
 
Quand j'éxécute se programme il faut environ 20 secondes avant qu'il m'affiche le numéro d'erreur 10060 qui signifie Délai de connection dépassé : ça me semble beaucoup pour un socket non-bloquant !!! Avez-vous une explication ?
 

Code :
  1. sock = socket(AF_INET,SOCK_STREAM,0);
  2.     /* LINUX: */
  3.     //fcntl (sock, F_SETFL, O_NONBLOCK);                                     
  4.     /* WINDOWS: */
  5.     if(ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking)<0){
  6.         perror("La socket ne peut être rendu non-bloquante car" );
  7.         cerr<<"On continue quand même avec socket bloquante. Patience."<<endl;
  8.     }
  9.     if(connect(sock, (SOCKADDR *)&sin, sizeof(sin))<0){
  10.  cout<<WSAGetLastError()<<endl;
  11.         exit(1);
  12.     }


Message édité par casafa le 25-02-2006 à 20:15:22
n°1313928
Profil sup​primé
Posté le 26-02-2006 à 22:12:47  answer
 

Pourquoi est ce qu il y a
bind(sock, (SOCKADDR *)&sin, sizeof(sin));
c est pour les serveurs pas les clients ?

n°1314046
casafa
Posté le 27-02-2006 à 09:53:22  profilanswer
 

eviljojo ==> re-lie mon message juste au dessus du tien:  je dit exactement la même chose que toi.

n°1314794
Profil sup​primé
Posté le 27-02-2006 à 20:38:13  answer
 

Oups désolé.

n°1349349
lilimali
Posté le 19-04-2006 à 09:28:43  profilanswer
 

Salut à tous !
 
Il est peut-être un peu tard pour toi mais je me dis que ça peut servir à d'autres.
Je crois que ton souci provient de la variable nonblocking que tu initialises à 0 alors qu'elle doit valoir 1 si tu veux rendre tes sockets non-bloquantes par un ioctlsocket. C'est la raison pour laquelle tu bloques toujours sur le connect.
 
Hope that helps !

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [Débutant] Socket

 

Sujets relatifs
ptit'pb à résoudre, débutant total[resolu]Debutant en php - derniere connection
(question débutant) Afficher du texte à partir d'un .txtDébutant en POO, class mysql php5
[JAVA - Débutant] - Probleme premier programme en JAVAstructure if - else (débutant)
Débutant...clé sympa du registre (debutant)
[Débutant] Socket en C + interaction avec du PHP[Debutant] Pb avec ObjectOutputStream et les socket
Plus de sujets relatifs à : [Débutant] Socket


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR