prob avec struct sockaddr_in et inet_addr

prob avec struct sockaddr_in et inet_addr - C - Programmation

Marsh Posté le 24-03-2006 à 07:28:09    

Bonjour,
j'essaie de creer un prog client qui puisse faire de la communication ip avec un serveur telnet.
Je butte sur un pb voici un partie du prog.
#include <stdio.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<netdb.h>
#include <string.h>
 
main(argc,argv)
int argc;
char* argv[];
{
int sock_com,port=23;
struct sockaddr_in adresse_distante;
struct servent num_port;
unsigned long chif_addr;
struct in_addr adresse;
printf("\nadresse de argv[1] %s",argv[1]);
if ((sock_com=socket(AF_INET,SOCK_STREAM,0))<0)
        perror("\nCreation de la socket echouee" );
printf("\nsocket cree" );
memset (& adresse_distante,0,sizeof(struct sockaddr_in));
printf("\ninitialisation du bloc memoire adresse_distante" );
adresse_distante.sin_family=AF_INET;
printf("\nAF_INET OK" );
adresse_distante.sin_port=htons(port);
printf("\nport OK" );
chif_addr=inet_addr(argv[1]);
printf("\nresultat %X",chif_addr);
if((adresse.s_addr=inet_addr(argv[1]))==INADDR_NONE)
/*if((adresse_distante.sin_addr.s_addr=inet_addr(argv[1]))==INADDR_NONE)*/;
perror("\nAdresse distante inconnue" );
free(adresse);
}
 
Quand je compile j'obtients un mmessg
 
/usr/ccs/bin/ld: (Warning) At least one PA 2.0 object file (communication1.o) was detected. The linked output may not run on a PA 1.x system.
que je ne comprend pas mais j'obtients un exe quand meme et quad je lance cet exe avec l'argument 127.0.0.1 je recois:
 
msgcnt 214 vxfs: mesg 001: vx_nospace - /dev/vg00/lvol5 file system full (1 block extent)
Bus error
 
avec l'argument 192.168.1.2
 
Memory fault(coredump)
quel est le prob dans l'attribution de l@ ip distante?

Reply

Marsh Posté le 24-03-2006 à 07:28:09   

Reply

Marsh Posté le 24-03-2006 à 09:24:24    

yartempion a écrit :

Quand je compile j'obtients un mmessg


Il faudrait déjà que ça compile...


Project   : forum
Compiler  : GNU GCC Compiler (called directly)
Directory : /home/edelahaye/dev-c/forum/
--------------------------------------------------------------------------------
Switching to target: default
Compiling: ../main.c
../main.c:8: warning: return type defaults to 'int'
../main.c:8: warning: function declaration isn't a prototype
../main.c: In function 'main':
../main.c:26: error: implicit declaration of function 'inet_addr'
../main.c:26: warning: nested extern declaration of 'inet_addr'
../main.c:27: warning: format 'BFFFED2C' expects type 'unsigned int', but argument 2 has type 'long unsigned int'
../main.c:31: error: implicit declaration of function 'free'
../main.c:31: warning: nested extern declaration of 'free'
../main.c:13: warning: unused variable 'num_port'
../main.c:32:2: warning: no newline at end of file
Process terminated with status 1 (0 minutes, 1 seconds)
2 errors, 7 warnings
 


Une fois que ça compile :

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. /* sockets */
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9.  
  10. int main(int argc, char* argv[])
  11. {
  12.   int sock_com, port = 23;
  13.   struct sockaddr_in adresse_distante;
  14.   unsigned long chif_addr;
  15.   struct in_addr adresse;
  16.  
  17.   printf("\nadresse de argv[1] %s", argv[1]);
  18.   if ((sock_com = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  19.      perror("\nCreation de la socket echouee" );
  20.   printf("\nsocket cree" );
  21.   memset (& adresse_distante, 0, sizeof(struct sockaddr_in));
  22.   printf("\ninitialisation du bloc memoire adresse_distante" );
  23.   adresse_distante.sin_family = AF_INET;
  24.   printf("\nAF_INET OK" );
  25.   adresse_distante.sin_port = htons(port);
  26.   printf("\nport OK" );
  27.   chif_addr = inet_addr(argv[1]);
  28.   printf("\nresultat %lX", chif_addr);
  29.   if ((adresse.s_addr = inet_addr(argv[1])) == INADDR_NONE)
  30.   {
  31.      /*if((adresse_distante.sin_addr.s_addr=inet_addr(argv[1]))==INADDR_NONE)*/
  32.      perror("\nAdresse distante inconnue" );
  33.   }
  34.   perror("\nAdresse distante inconnue" );
  35.   return 0;
  36. }


Ce programme est extrêmement fragile.  

  • Il manque un test pour savoir si on a bien passé les paramètres...
  • Pour socket(), le premier paramètre est 'Protocol Family', soit PF_xxx et non 'Address Family' AF_xxx.
  • Si l'ouverture du socket echoue, le code continue avec un socket invalide...
  • Le caractère '\n' indique la fon de ligne et non le début...
  • Un socket ouvert doit être refermé proprement
  • Le reste du code(IP/Port) n'a pas de sens tand qu'il n'y a pas de bind() ou équivallent...

Ceci fonctionne correctement

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. /* sockets */
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <unistd.h>
  10.  
  11. int main(int argc, char* argv[])
  12. {
  13.   if (argc > 1)
  14.   {
  15.      printf("adresse distante ='%s'\n", argv[1]);
  16.      {
  17.         int sock_com = socket(PF_INET, SOCK_STREAM, 0);
  18.  
  19.         if (sock_com >= 0)
  20.         {
  21.            printf("socket %d cree\n", sock_com);
  22.  
  23.            close (sock_com), sock_com = -1;
  24.         }
  25.         else
  26.         {
  27.            perror("socket()" );
  28.         }
  29.      }
  30.   }
  31.   else
  32.   {
  33.      puts("usage myapp <adresse IP>" );
  34.   }
  35.   return 0;
  36. }


Message édité par Emmanuel Delahaye le 24-03-2006 à 10:34:55

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-03-2006 à 12:37:02    

Slt
Merci d'avoir pris le pb
J'ai remanie la routine et voici ce que ca donne:
 
 
#include <stdio.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<netdb.h>
#include <string.h>
#include<unistd.h>
#define LG_BUFFER 1024
 
main(argc,argv)
int argc;
char** argv;
{
char buffer[LG_BUFFER];
int sock_com,nb_lus,port=23;
struct sockaddr_in adresse_distante;
struct servent num_port;
printf("\nadresse de argv[1] %s",argv[1]);
memset (& adresse_distante,0,sizeof(struct sockaddr_in));
printf("\ninitialisation du bloc memoire adresse_distante" );
adresse_distante.sin_family=AF_INET;
printf("\nAF_INET OK" );
adresse_distante.sin_port=htons(port);
printf("\nport OK" );
if((adresse_distante.sin_addr.s_addr=inet_addr(argv[1]))==INADDR_NONE)
perror("\nAdresse distante inconnue" );
else
printf("\nResultat de inet_addr %X\n",adresse_distante.sin_addr.s_addr);
printf("\ncreation de la socket" );
if ((sock_com=socket(AF_INET,SOCK_STREAM,0))<0)
 perror("\nCreation de la socket echouee" );
printf("\nsocket cree Ref sock_com=%d",sock_com);
printf("\ntentative de connection au distant" );
if(connect(sock_com,&adresse_distante,sizeof(struct sockaddr_in))<0)
 {
 perror("\nerreur sur connect\n" );
 exit(1);
 }
setvbuf(stdout,_IONBF,0);
while(1)
 {
 if((nb_lus=read(sock_com,buffer,LG_BUFFER))==0)
 break;
 if(nb_lus<0)
  {
  perror("\nerreur sur lecture socket\n" );
  exit(1);
  }
 write(STDOUT_FILENO,buffer,nb_lus);
 }
close(sock_com);
printf("\n" );
/*free(adresse);*/
}
 
 Quand je lance ca marche  
./communication1 127.0.0.1              
 
adresse de argv[1] 127.0.0.1
initialisation du bloc memoire adresse_distante
AF_INET OK
port OK
Resultat de inet_addr 7F000001
 
creation de la socket
socket cree Ref sock_com=3
tentative de connection au distant »$
 
mais rien de lisible sur la socket pourquoi?
Pourquoi je n'arrive pas a lire les donnees envoyes par mon serveur telnet?

Reply

Marsh Posté le 25-03-2006 à 17:23:25    

salut,
 
J'essaie de créer un serveur UDP et un client UDP qui echangent des messages. Mais je n'arrive pas a reccuperer l adresse IP du client dans mon serveur.
je fais :
 
printf("Adresse %s\n", inet_ntoa(son_s->sin_addr));
 
et il imprime :
 
Adresse 0.0.0.0
 
I need help..
 
Merci.

Reply

Marsh Posté le 25-03-2006 à 17:27:34    

dounia2 a écrit :

salut,
 
J'essaie de créer un serveur UDP et un client UDP qui echangent des messages. Mais je n'arrive pas a reccuperer l adresse IP du client dans mon serveur.
je fais :
 
printf("Adresse %s\n", inet_ntoa(son_s->sin_addr));
 
et il imprime :
 
Adresse 0.0.0.0
 
I need help..
 
Merci.


 
tiens, on finit son tp de sr03 :)
 
il faudrait un peu plus de precisions pour pouvoir repondre

Reply

Marsh Posté le 25-03-2006 à 17:33:36    

ArthurDent a écrit :

tiens, on finit son tp de sr03 :)
 
il faudrait un peu plus de precisions pour pouvoir repondre


 
Lol, j'en deduis que tu fais sr03 aussi:)
 
Ben je n'arrive tout simplement pas a imprimer l'adresse de mon client. Et je ne sais pas ou aller la chercher dans la structure sockaddr_in..

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "my_socks.h"
  5. /* Note : l'adrese IP du serveur est localost si le client et le serveur sont sur la */
  6. /*     même machine.                 */
  7. int main(int argc, char *argv[])
  8. {
  9. struct sockaddr_in* mon_s;
  10. struct sockaddr_in* son_s;
  11. int     sd, n, num_port_udp;
  12. int     *fromlen;
  13. message*   rcv_mess;
  14. message* send_mess;
  15. int i;
  16. if (argc != 2) {
  17.  printf("Usage : %s <numero_port_udp>\n", argv[0]);
  18.  exit(1);
  19. }
  20. num_port_udp = atoi(argv[1]);
  21. /* Allocation mémoire                 */
  22. mon_s   = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
  23. son_s   = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
  24. rcv_mess   = (message *)malloc(sizeof(message));
  25. send_mess = (message*)malloc(sizeof(message));
  26. fromlen  = (int *)malloc(sizeof(int));
  27. /* On ouvre un socket en mode UDP, datagramme, sur le domaine PF_INET     */
  28. if((sd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
  29. {
  30.  perror("udpser.c: err socket" );
  31.  affiche_errno();
  32. }
  33. /* On remplit la structure d addresse du client par des zeros pour l initialisation */
  34. /* Note du man: "BSD 4.3. bezo est déconseillée, utilisez plutôt memset."   */
  35. memset((char*)mon_s, 0, sizeof(*mon_s));
  36. /* On initialise les champs de la structure.          */
  37. /* Initialisation de l adresse IP de la machine avec n importe quelle carte   */
  38. mon_s->sin_addr.s_addr = INADDR_ANY;
  39. mon_s->sin_family = htonl(AF_INET);
  40. /*initialisation du port du serveur avec des octets en format reseau    */
  41. mon_s->sin_port = htons(num_port_udp);
  42. if((n = bind(sd, (struct sockaddr*)mon_s, sizeof(*mon_s))) == -1)
  43. {
  44.  perror("udpser.c: err bind" );
  45.  affiche_errno();
  46. }
  47. /* Longueur de l adresse recuperee par le serveur (envoyée par le client)   */
  48. *fromlen = sizeof(son_s);
  49. strcpy(send_mess->mtext, "Seurver reponds et envoie un message" );
  50. printf("---------------[Serveur]-----------------" );
  51. printf("\nBind to         : %d %d\n", sd, num_port_udp);
  52. if((n = recvfrom(sd, rcv_mess, sizeof(message), 0, (struct sockaddr*)son_s, (socklen_t *)fromlen)) == -1)
  53. {
  54.  perror("udpser.c: err recvfrom" );
  55.  affiche_errno();
  56. }
  57. printf("Message recu      : \"%s\"\n", rcv_mess->mtext);
  58. printf("Reçu from         : %x %d\n", ntohl(son_s->sin_addr.s_addr), ntohs(son_s->sin_port));
  59. printf("Adresse IP client: %s\n", inet_ntoa(son_s->sin_addr));
  60. printf("Serveur envoie message...\n" );
  61. if((n = sendto(sd, send_mess, sizeof(message), 0, (struct sockaddr*)son_s, sizeof(*son_s))) == -1)
  62. {
  63.  perror("udpser.c: err sendto" );
  64.  affiche_errno();
  65. }
  66. printf("FIN\n\n" );
  67. /* Libération de la mémoire               */
  68. free(mon_s);
  69. free(son_s);
  70. free(send_mess);
  71. free(rcv_mess);
  72. free(fromlen);
  73. return 0;
  74. }


 
Voila a quoi ca ressemble :s

Reply

Marsh Posté le 25-03-2006 à 17:41:25    

essaie en rajoutant ça au debut de ton code
 

Code :
  1. struct hostent *pHostent_hs = gethostbyname(argv[1]);
  2. bcopy(pHostent_hs->h_addr, &son_s->sin_addr.s_addr, pHostent_hs->h_length);


 
où argv[1] est le nom d'hote que tu passes en parametre, remplace par "localhost" si tu le pase pas en parametre


Message édité par ArthurDent le 25-03-2006 à 17:45:16
Reply

Marsh Posté le 25-03-2006 à 17:46:49    

mais en faisant ca je reccupere l @ IP de mon serveur, je me trompe? moi je veux celle du client, donc celle de son_s apres le recvfrom().

Reply

Marsh Posté le 25-03-2006 à 17:52:28    

ah, ok, je pensais que c'etait le code du client

Reply

Marsh Posté le 25-03-2006 à 17:54:21    

desolée j'avais oublié de préciser que c t le code du server:)

Reply

Marsh Posté le 25-03-2006 à 17:54:21   

Reply

Marsh Posté le 25-03-2006 à 18:07:51    

il faut mettre  

Code :
  1. *fromlen = sizeof(*son_s);


a la place de  

Code :
  1. *fromlen = sizeof(son_s);


 
sinon tu recupere la taille du pointeur (4) et pas la taille de sockaddr_in

Reply

Marsh Posté le 25-03-2006 à 18:17:53    

ca marche!
 
Merci enormement:)

Reply

Marsh Posté le 25-03-2006 à 18:25:32    

Une dernere question:  
a l execution  des fois j'obtient:  
 
> ./udpser 4679  
udpser.c: err bind: Address already in use  
 
 errno =29  
Exit 1  
 
Tu sais comment liberer le port?  
 
Merci encore ArthurDent

Reply

Marsh Posté le 25-03-2006 à 18:45:36    

Rslt,
Je suis toujours bloque par cette histoire de lecture sur la socket du client qui se connecte a un serveur telnet comment recuperer les donnees ou ne faudrait il pas activer un NVT sur la socket?

Reply

Marsh Posté le 25-03-2006 à 19:50:58    

yartempion a écrit :

Rslt,
Je suis toujours bloque par cette histoire de lecture sur la socket du client qui se connecte a un serveur telnet comment recuperer les donnees ou ne faudrait il pas activer un NVT sur la socket?


 
c'est quoi NVT?
 
pourquoi n'utilise tu pas recv au lieu de read?

Reply

Marsh Posté le 25-03-2006 à 22:37:52    

Quel est la difference entre un recv et read.
NVT network Virtual terminal permet d'effectuer une conversion des donnees et de modifier les caracteristique d'un terminal.
Exp Quand on saisi au clavier les donnees ne sont prises en compte que si on appuie sur la touche enntrer on modifier ce comportement pour que la frappe soit lue immediatement. Les machines code les donnees sur un certains nombre de bits alors que sur le reseau il est parfois preferable de les coder d'une maniere normalisee pour que toutes les machines puissent les interpreter.

Reply

Marsh Posté le 26-03-2006 à 22:55:52    

yartempion a écrit :

J'ai remanie la routine et voici ce que ca donne:
#include <stdio.h>


Je ne regarde pas ça tant qu'il n'y a pas les balises code... C'est compliqué de clicker sur http://forum-images.hardware.fr/icones/message/fixe.gif ou http://forum-images.hardware.fr/icones/message/c.gif ?

Code :
  1. if ((sock_com=socket(AF_INET,SOCK_STREAM,0))<0)


Je parle aux murs ou quoi ?

Citation :

Pour socket(), le premier paramètre est 'Protocol Family', soit PF_xxx et non 'Address Family' AF_xxx.

Message cité 1 fois
Message édité par Emmanuel Delahaye le 26-03-2006 à 22:59:34

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 27-03-2006 à 00:49:35    

Emmanuel Delahaye a écrit :

Je ne regarde pas ça tant qu'il n'y a pas les balises code... C'est compliqué de clicker sur http://forum-images.hardware.fr/ic [...] e/fixe.gif ou http://forum-images.hardware.fr/icones/message/c.gif ?

Code :
  1. if ((sock_com=socket(AF_INET,SOCK_STREAM,0))<0)


Je parle aux murs ou quoi ?

Citation :

Pour socket(), le premier paramètre est 'Protocol Family', soit PF_xxx et non 'Address Family' AF_xxx.



Salut et toutes mes excuses j'avais oublie

Code :
  1. #include <stdio.h>
  2. #include <netinet/in.h>
  3. #include<sys/socket.h>
  4. #include<netdb.h>
  5. #include <string.h>
  6. #include<unistd.h>
  7. #define LG_BUFFER 1024
  8. main(argc,argv)
  9. int argc;
  10. char** argv;
  11. {
  12. char buffer[LG_BUFFER];
  13. int sock_com,nb_lus,port=23;
  14. struct sockaddr_in adresse_distante;
  15. struct servent num_port;
  16. printf("\nadresse de argv[1] %s",argv[1]);
  17. memset (& adresse_distante,0,sizeof(struct sockaddr_in));
  18. printf("\ninitialisation du bloc memoire adresse_distante" );
  19. adresse_distante.sin_family=AF_INET;
  20. printf("\nAF_INET OK" );
  21. adresse_distante.sin_port=htons(port);
  22. printf("\nport OK" );
  23. if((adresse_distante.sin_addr.s_addr=inet_addr(argv[1]))==INADDR_NONE)
  24. perror("\nAdresse distante inconnue" );
  25. else
  26. printf("\nResultat de inet_addr %X\n",adresse_distante.sin_addr.s_addr);
  27. printf("\ncreation de la socket" );
  28. if ((sock_com=socket(AF_INET,SOCK_STREAM,0))<0)
  29. perror("\nCreation de la socket echouee" );
  30. printf("\nsocket cree Ref sock_com=%d",sock_com);
  31. printf("\ntentative de connection au distant" );
  32. if(connect(sock_com,&adresse_distante,sizeof(struct sockaddr_in))<0)
  33. {
  34. perror("\nerreur sur connect\n" );
  35. exit(1);
  36. }
  37. setvbuf(stdout,_IONBF,0);
  38. while(1)
  39. {
  40. if((nb_lus=read(sock_com,buffer,LG_BUFFER))==0)
  41. break;
  42. if(nb_lus<0)
  43.   {
  44.   perror("\nerreur sur lecture socket\n" );
  45.   exit(1);
  46.   }
  47. write(STDOUT_FILENO,buffer,nb_lus);
  48. }
  49. close(sock_com);
  50. printf("\n" );
  51. /*free(adresse);*/
  52. }


Reply

Marsh Posté le 27-03-2006 à 09:18:16    

Salut,
Je crois qu'on peut tout aussi bien utiliser AF_INET que PF_INET le probleme ne vient d'un erruer programme mais plutot d'une erreur protocolaire du telnet. Je pense qu'il faudrai que je vois comment sont codes les octet et que je traverse un NVT pour les transformer du format telnet au format de ma machine. Pour l'instant je n'y artive pas.

Reply

Marsh Posté le 27-03-2006 à 09:21:53    

yartempion a écrit :

Je crois qu'on peut tout aussi bien utiliser AF_INET que PF_INET


Non. Je ne dis pas que c'est ça la cause de tes problèmes, mais commence déjà par utiliser les fonctions correctement :
 
http://www.linux-kheops.com/doc/ma [...] ket.2.html


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 27-03-2006 à 10:17:04    

Merci pour le lien.
Je ne vois pas trop quelle fonction peche.

Reply

Marsh Posté le 27-03-2006 à 12:14:37    

Emmanuel Delahaye a écrit :

Non. Je ne dis pas que c'est ça la cause de tes problèmes, mais commence déjà par utiliser les fonctions correctement :
 
http://www.linux-kheops.com/doc/ma [...] ket.2.html


Vu que le lien concerne socket(), y'a pas trop à chercher... D'autre part, ce lien précise que le paramètre est bien PF_INET et non AF_INET comme tu l'a ecrit de façon erronée  
 
Nota : Cette erreur est fréquente, y compris dans de nombreux tutoriels et exemples sur le net ou dans des cours de fac et autres. La confusion vient de ce que la valeur de ces deux macros est souvent 0, ce qui fait que l'erreur est sans effet dans la plupart des cas...  
 
Mais ne pas respecter la définition et l'usage des fonctions, c'est mal.


Message édité par Emmanuel Delahaye le 27-03-2006 à 12:15:39

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 27-03-2006 à 13:15:33    

En effet sur toutes les docs que j'ai consulte AF_INET est indique.
Visiblement AF_INET doit servir pour les struct sockaddr_in et PF_INET pour les socket mais je ne suis plus tres sur.
Mais le pb reste entier, je ne lis toujours tien sur la socket.

Reply

Marsh Posté le 27-03-2006 à 13:59:17    

Citation :

/usr/ccs/bin/ld: (Warning) At least one PA 2.0 object file (communication1.o) was detected. The linked output may not run on a PA 1.x system.


 
si ld te sort ca il est probable que ca merde à l'execution, c'est un probleme qui concerne l'installation de la bibliothèque concernée

Reply

Marsh Posté le 28-03-2006 à 12:14:37    

Bonjour,
Je n'ai toujours pas resolut mon probleme.
Je pense etre sur la bonne voie en faisant une modif sur le terminal d'entree. D'apres ce que j'ai compris il faut passer l'entree en mode brut afin de coller aux exigences de telnet.
Si quelqu'un connait la solution merci

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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