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

  FORUM HardWare.fr
  Programmation
  C++

  [C - Newby] Telnet en C

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C - Newby] Telnet en C

n°550885
dudul51
Posté le 26-10-2003 à 17:22:26  profilanswer
 

Voilà mon problème : j'essaie d'écrire un client qui se connecte à un site web à partir d'une socket en tcp. Ensuite l'utilisateur peut taper une requête HTTP vers se serveur. La réponse du serveur est alors affichée à l'écran. Voici mon code :
 

Code :
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <unistd.h>
  5. #include <netdb.h>
  6. main()
  7. {
  8. int sock;
  9. struct hostent* he;
  10. struct sockaddr_in cli, srv;
  11. int size=sizeof(struct sockaddr_in);
  12. char buf[1024];
  13.         char buf2[1024];
  14. sock=socket(AF_INET,SOCK_STREAM,0);
  15. cli.sin_family=AF_INET;
  16. he=gethostbyname("localhost" );
  17. memcpy(&cli.sin_addr,he->h_addr,sizeof(cli.sin_addr));
  18. cli.sin_port=htons(80);
  19.         srv.sin_family=AF_INET;
  20. he=gethostbyname("www.yahoo.fr" );
  21. memcpy(&srv.sin_addr,he->h_addr,sizeof(srv.sin_addr));
  22. srv.sin_port=htons(80);
  23. int a=bind(sock,(struct sockaddr*)&cli,sizeof(cli));
  24. if(a!=0) {perror("Bind : " );exit(0);}
  25. int b=connect(sock,(struct sockaddr*)&srv,size);
  26. if(b!=0) {perror("Connect : " );exit(0);}
  27. printf("Entrer la requete :\n" );
  28. scanf("%s",buf);
  29.         send(sock,buf,sizeof(buf),0);
  30. recv(sock,buf2,sizeof(buf),0);
  31. printf("%s\n",buf2);
  32. close(sock);
  33. }


 
avec ce code j'essaie de me connecter sur yahoo pour envoyer ma requête mais j'ai une erreur au niveau du connect : Invalid argument et je ne voit pas d'où ça vient : de la construction de srv, des ports???
Quelqu'un peut m'aider?

mood
Publicité
Posté le 26-10-2003 à 17:22:26  profilanswer
 

n°550890
blackgodde​ss
vive le troll !
Posté le 26-10-2003 à 17:25:08  profilanswer
 

il y a une rubrique c, et une c++, ici on est dans la c++ :D
 
sinon, tu veux apparement binder ton port local 80, as-tu vérifié qu'il n'etait pas déjà utilisé ?


---------------
-( BlackGoddess )-
n°550895
dudul51
Posté le 26-10-2003 à 17:27:32  profilanswer
 

oups dsl pour la rubrique.
mon port 80 est le port http de ma machine donc je pense que c'est le bon port à utiliser. De plus l'erreur ne viens pas du bind mais du connect.

n°551002
dudul51
Posté le 26-10-2003 à 19:51:30  profilanswer
 

Personne n'a d'idées?

n°551006
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 26-10-2003 à 19:54:39  profilanswer
 

tu compiles sous quel OS ?


---------------
J'ai un string dans l'array (Paris Hilton)
n°551024
dudul51
Posté le 26-10-2003 à 20:14:58  profilanswer
 

Linux Red Hat 8 avec gcc

n°551053
petitjeans​eb
Posté le 26-10-2003 à 21:09:59  profilanswer
 

pour détereminer les pbs et débuguer plus facilement ton application, sécurise la déjà : par exemple, vérifie la valeur de retour de tes fonctions, style :  
if(sock = socket(...) == false)
// affiche message
 
ça t'aidera à savoir ce qui marche ou pas. Prendre cette habitude est primordiale en prod, et spécialement en socket où ça ne marche jamais comme on veut

n°551073
dudul51
Posté le 26-10-2003 à 21:44:17  profilanswer
 

Code :
  1. int a=bind(sock,(struct sockaddr*)&cli,sizeof(cli));
  2. if(a!=0) {perror("Bind : " );exit(0);}

 
 

Code :
  1. int b=connect(sock,(struct sockaddr*)&srv,size);
  2. if(b!=0) {perror("Connect : " );exit(0);}


 
C'est grâce à ces tests que j'ai pu voir que le connect ne marche pas : perror() du connect me retourne invalid argument

n°551147
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 26-10-2003 à 23:16:59  profilanswer
 

Regarde ces lignes :
 
memcpy(&cli.sin_addr,he->h_addr,sizeof(cli.sin_addr));
memcpy(&srv.sin_addr,he->h_addr,sizeof(srv.sin_addr));
 
Dans la définition de la structure sockaddr_in, le membre sin_addr est une structure de type in_addr. T'as pas l'impression de faire un peu n'importe quoi là ? Pas étonnant que je me prenne une segmentation fault si je lance ton programme en n'étant pas connecté au net... :sarcastic:
 
Pour info, le membre qui contient les adresses est sockaddr_in.sin_addr.s_addr.
 
Ce qui nous donne :

Code :
  1. memcpy(&cli.sin_addr.s_addr,he->h_addr,sizeof(struct in_addr));
  2. memcpy(&srv.sin_addr.s_addr,he->h_addr,sizeof(struct in_addr));


 
Regarde au moins la définition des structures la prochaine fois...


Message édité par Harkonnen le 26-10-2003 à 23:17:22
n°551553
dudul51
Posté le 27-10-2003 à 14:43:07  profilanswer
 

ok mais pourquoi ça fonctionne parfaitement lorsque l'on fait tourner le serveur et le client sur la même machine? j'ai compilé avec ce que tu m'as gentiment conseillé mais j'ai toujours la même erreur : Connect:Invalid Argument (et un segmentation fault quand je ne suis pas connecté à Internet :wahoo: )

mood
Publicité
Posté le 27-10-2003 à 14:43:07  profilanswer
 

n°552035
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 27-10-2003 à 22:40:23  profilanswer
 

J'ai repris ton source un peu plus en détail, je l'ai modifié et il marche. Ne compte pas sur moi pour te donner le source, ça serait trop facile. Je te donne juste quelques pistes :
 
- il te faut 2 sockets : 1 client et 1 serveur. Pourquoi 2 sockets ? Tout simplement parce que le 1er paramètre de la fonction socket() change selon qu'il s'agit d'un client ou d'un serveur et leur fonction n'est pas la même
- les memset() pour vider la structure sockaddr_in, c'est bien, manges en
- si tu veux éviter la segmentation fault en n'étant pas connecté au net, je te conseille de tester la valeur de retour de gethostbyname("www.yahoo.fr" )
- la valeur que tu donnes au membre sin_family de ta structure sockaddr_in n'est pas bon. regarde plutot du coté de he->h_addrtype
- si tu tiens vraiment à utiliser le membre sin_addr de ta structure sockaddr_in, tape plutot un truc du genre :

Code :
  1. memcpy((char *)&srv.sin_addr,he->h_addr,he->h_length);


 
voici ce que j'obtiens :

Citation :


[harkonnen@localhost Documents]# ./socket
Entrer la requete :
GET index.html
The document has moved <A HREF="http://de.docs.yahoo.com/notfound.html">here</A>.<P>


 
à toi de jouer maintenant...


Message édité par Harkonnen le 27-10-2003 à 22:41:48
n°552134
matafan
Posté le 28-10-2003 à 05:55:27  profilanswer
 

Heu pourquoi deux sockets ? :heink:

n°552171
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 09:17:56  profilanswer
 

Il n'a besoin que d'un socket effectivement, mais je suppose que s'il a mis le socket "localhost", c'est qu'il compte l'utiliser par la suite [:sinclaire]
Mais c'est clair que tel qu'il est codé dans son source, il ne sert à rien du tout (il est bindé, mais sans listen() ou connect() derrière, etc..)


---------------
J'ai un string dans l'array (Paris Hilton)
n°552194
dudul51
Posté le 28-10-2003 à 09:38:56  profilanswer
 

je vois pas pourquoi il faudrait 2 sockets. Le listen est géré par le serveur. Ce code fonctionne parfaitement lorsque je fais tourner un serveur sur une machine du même réseau que le client.

n°552201
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 09:52:05  profilanswer
 

Alors à quoi te servent ces lignes ?

Code :
  1. sock=socket(AF_INET,SOCK_STREAM,0);
  2. cli.sin_family=AF_INET;
  3. he=gethostbyname("localhost" );
  4. memcpy(&cli.sin_addr,he->h_addr,sizeof(cli.sin_addr));
  5. cli.sin_port=htons(80);
  6. [...]
  7. int a=bind(sock,(struct sockaddr*)&cli,sizeof(cli));


Pourquoi bindes tu un socket avec localhost si ensuite tu utilises ce socket pour te connecter sur yahoo ?
J'ai supprimé ces lignes et ça fonctionne très bien, en faisant les modifs que je t'ai donné plus haut, j'arrive à me connecter sur le serveur de yahoo sans problème


---------------
J'ai un string dans l'array (Paris Hilton)
n°552271
dudul51
Posté le 28-10-2003 à 10:59:24  profilanswer
 

il faut bien construire la structure sockaddr_in cli pour savoir sur quel port on travaille sur la machine local nan?
le bind est là pour associer un port à la socket.


Message édité par dudul51 le 28-10-2003 à 11:02:43
n°552286
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 11:07:31  profilanswer
 

pourquoi veux tu indiquer le port sur lequel travaille la machine locale ?
moi j'ai enlevé de ton source toute la partie qui concerne la structure cli (les lignes de mon post précédent), et ça marche bien [:sinclaire]
 
edit: le bind() serait utile si tu faisais un listen() derrière, pour un connect(), à mon avis c'est inutile


Message édité par Harkonnen le 28-10-2003 à 11:15:16

---------------
J'ai un string dans l'array (Paris Hilton)
n°552298
dudul51
Posté le 28-10-2003 à 11:16:16  profilanswer
 

parce qu'une socket à toujours un numéro de port associé!  
de toute façon l'erreur ne vient pas de là.
 
edit: en tcp on a:
 
client : bind puis connect (il est vrai que le bind n'est pas obligatoire que le connect s'en charge).
serveur : listen puis accept
 
le client ne fait jamais de listen et donc jamais d'accept.


Message édité par dudul51 le 28-10-2003 à 11:18:41
n°552309
LetoII
Le dormeur doit se réveiller
Posté le 28-10-2003 à 11:19:50  profilanswer
 

dudul51 a écrit :

parce qu'une socket à toujours un numéro de port associé!  
de toute façon l'erreur ne vient pas de là.


 
J'en suis pas si sûr... Déjà ton utilisation du port 80 pour le client est louche, j'essairai avec un port > 1024, et puis la plus part du temps on se fout de savoir quel port on utilise pour sortir  [:spamafote]


---------------
Le Tyran
n°552311
LetoII
Le dormeur doit se réveiller
Posté le 28-10-2003 à 11:20:59  profilanswer
 

Harkonnen a écrit :

pourquoi veux tu indiquer le port sur lequel travaille la machine locale ?
moi j'ai enlevé de ton source toute la partie qui concerne la structure cli (les lignes de mon post précédent), et ça marche bien [:sinclaire]
 
edit: le bind() serait utile si tu faisais un listen() derrière, pour un connect(), à mon avis c'est inutile


 
Si j'ai bien tout compris à la chose, c utile si tu veux utiliser un port spécifique pour sortir... mais la son port 80 c'est une mauvaise idée.


---------------
Le Tyran
n°552381
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 11:49:53  profilanswer
 

dudul51 a écrit :

parce qu'une socket à toujours un numéro de port associé!  


oui merci je le sais ;)
mais si tu ne fais aucun listen(), je vois pas l'utilité de binder ton socket à localhost
 

dudul51 a écrit :


de toute façon l'erreur ne vient pas de là.


Non elle ne vient pas de là. J'ai corrigé ton source selon les indications que je t'ai donné plus haut, et ça fonctionne très bien, avec ou sans le bind() de toute façon. Essaie de trouver l'erreur par toi même, je ne t'aiderais pas si je te donne le source tout fait.


---------------
J'ai un string dans l'array (Paris Hilton)
n°552752
dudul51
Posté le 28-10-2003 à 16:29:08  profilanswer
 

LetoII a écrit :


 
Si j'ai bien tout compris à la chose, c utile si tu veux utiliser un port spécifique pour sortir... mais la son port 80 c'est une mauvaise idée.


 
c'est le port http le port 80 et je veux me connecter à un serveur pour exécuter une requête http.

n°552759
LetoII
Le dormeur doit se réveiller
Posté le 28-10-2003 à 16:34:04  profilanswer
 

dudul51 a écrit :


 
c'est le port http le port 80 et je veux me connecter à un serveur pour exécuter une requête http.


 
Oui mais tu ton client peut utiliser n'importe quel port pour sortir.


---------------
Le Tyran
n°552774
dudul51
Posté le 28-10-2003 à 16:41:44  profilanswer
 

c'est vrai, je viens d'essayer avec un port différent et ça marche. Je pensais que la socket du client devait être associée elle aussi au port 80. Merci.

n°552775
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 16:41:58  profilanswer
 

De toute façon, un bind() est inutile si tu cherches à te connecter à un site web, à mon avis. Un connect() suffit, et ensuite tu utilises les fonctions send() et recv() pour dialoguer avec le site.


---------------
J'ai un string dans l'array (Paris Hilton)
n°552780
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 28-10-2003 à 16:46:52  profilanswer
 

pour info, voici ce que j'ai fait :

Code :
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <unistd.h>
  5. #include <netdb.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. int main(int argc, char **argv)
  9. {
  10. int sock;
  11. struct hostent* he;
  12. struct sockaddr_in srv;
  13. char buf[1024];
  14. char buf2[1024];
  15. memset(&srv,0,sizeof(struct sockaddr_in));
  16. he=gethostbyname("www.yahoo.fr" );
  17. if (he == NULL) {
  18.  perror("www.yahoo.fr" );
  19.  return (-1);
  20. }
  21. srv.sin_family=he->h_addrtype;
  22. memcpy((char *)&srv.sin_addr,he->h_addr,he->h_length);
  23. srv.sin_port=htons(80);
  24. socksrv = socket(he->h_addrtype,SOCK_STREAM,0);
  25. int b=connect(socksrv,(struct sockaddr*)&srv,size);
  26. if(b != 0) {
  27.  perror("Connect" );
  28.  return(-1);
  29. }
  30. printf("Entrer la requete :\n" );
  31. scanf("%s",buf);
  32. send(socksrv,buf,sizeof(buf),0);
  33. recv(socksrv,buf2,sizeof(buf),0);
  34. printf("%s\n",buf2);
  35. close(socksrv);
  36. }


Message édité par Harkonnen le 28-10-2003 à 16:49:46

---------------
J'ai un string dans l'array (Paris Hilton)
n°552866
VisualC++
J'va y penser ...
Posté le 28-10-2003 à 17:51:39  profilanswer
 

Sinon tres bon site ici

n°553008
dudul51
Posté le 28-10-2003 à 21:44:50  profilanswer
 

Il est vrai que sans le bind() ça marche aussi. Merci pour ton aide.

n°553146
matafan
Posté le 29-10-2003 à 04:25:42  profilanswer
 

Pour info, si tu ne fais pas de bind(), alors le connect() prend un numéro de port aléatoire au dessus de 1024. Et c'est la bonne façon de faire, sauf besoin particulier (du genre un firewall qui ne laisse sortir que quelques ports bien particuliers).
 
Au final tu as côté serveur une socket bindée sur le port 80, et côté client une socket bindée sur un port arbitraire au dessus de 1024.

mood
Publicité
Posté le   profilanswer
 


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

  [C - Newby] Telnet en C

 

Sujets relatifs
[C - Newby] Communication par socket en UDP[software] cherche prog Telnet avec des MDI
PHP, socket & telnet... se logger sur un serveur distant [SOLVED][socket TCP] gestion de la deconnexion d1 client telnet
[Perl] Utiliser le module Net::Telnet sans l'avoir installé[perl] Exécuter un telnet dans un cgi perl
Autre Truc bizarre ! [Newby][newby inside] -> transformer application en applet
Classe pour faire du telnet (C'est pas du telnet, seulement l'api)Src Telnet fait avec winsock?
Plus de sujets relatifs à : [C - Newby] Telnet en C


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