Structure sockaddr_in

Structure sockaddr_in - C - Programmation

Marsh Posté le 25-03-2006 à 16:36:28    

Salut,
 
J'essaie de programmer un serveur UDP et un client UDP aui echangent des messages. Dans mon serveur je veux reccuperer l'adresse IP du client. Pour cela j imprime sut stdout "sin_addr.s_addr" mais je me retrouve avec une adresse nulle.
 
printf("Adresse IP client: %s \n", son_s->sin_addr.s_addr);
 
Quelqu'un peut m'aider?
 
Merci.


Message édité par dounia2 le 25-03-2006 à 17:01:11
Reply

Marsh Posté le 25-03-2006 à 16:36:28   

Reply

Marsh Posté le 25-03-2006 à 17:10:19    

> son_s->sin_addr.s_addr
- contient une adresse ip sous forme binaire
 
utilise une fonction de conversion:
 
char *inet_ntoa(struct in_addr in);
 

Reply

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

J'ai esseye avec  
 
printf("Adresse %s\n", inet_ntoa(son_s->sin_addr));
 
et il imprime  
 
Adresse 0.0.0.0
 
C'est normal?


Message édité par dounia2 le 25-03-2006 à 17:28:36
Reply

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

tu essaie d'afficher l'adresse de la machine sur laquelle le process s'execute ou celle de la machine avec laquelle tu communique?

Reply

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

J'esseye d'afficher l'adresse de la machine sur laquelle le process s'execute (si c une machine distante ca revient a dire la machine avec laquelle je communique, non?..enfin je ne vois pas vraiment la différence entre les deux)..

Reply

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

il faudrait que tu montre la partie de code qui accèpte la connexion client et récupère son adresse...
D où vient le ``son_s->sin_addr.s_addr``?

Reply

Marsh Posté le 25-03-2006 à 17:43:19    

nargy a écrit :

il faudrait que tu montre la partie de code qui accèpte la connexion client et récupère son adresse...
D où vient le ``son_s->sin_addr.s_addr``?


 
Voila le code, pourtant j'ai bien rempli les structures sockaddr_in..
En tout cas merci pour ton aide, je commence à etre fatiguée :)
 

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: \n" );
  60. printf("Adresse %s\n", inet_ntoa(son_s->sin_addr));
  61. /*for(i=0; i<4; i++)
  62. {//inet_ntoa
  63.  printf("%s", son_s->sin_addr.s_addr[i]);
  64.  if(i<3)
  65.   printf("." );
  66.  if(i=3)
  67.   printf("\n" );
  68. }*/
  69. printf("Serveur envoie message...\n" );
  70. if((n = sendto(sd, send_mess, sizeof(message), 0, (struct sockaddr*)son_s, sizeof(*son_s))) == -1)
  71. {
  72.  perror("udpser.c: err sendto" );
  73.  affiche_errno();
  74. }
  75. printf("FIN\n\n" );
  76. /* Libération de la mémoire               */
  77. free(mon_s);
  78. free(son_s);
  79. free(send_mess);
  80. free(rcv_mess);
  81. free(fromlen);
  82. return 0;
  83. }


 

Reply

Marsh Posté le 25-03-2006 à 18:08:13    

1°) INADDR_ANY=0.0.0.0
est utiliser pour indiquer que l on accepte toute adresse ip valide (un ordinateur peut en avoir plusieurs comme par ex. les passerelles internet)

Reply

Marsh Posté le 25-03-2006 à 18:12:57    

2°) il manque un connect quelquepart
 
le bind sert suelement à affecter une adresse ip à la socket, mais pour effecture la connection:
connect() -> côté client
listen() -> côté serveur

Reply

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

entre la ligne 55 et 68 ci sessus, il manque:
 
int socket_client=listen(sd,SOMAXCONN);
 

Reply

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

Reply

Marsh Posté le 25-03-2006 à 18:19:11    

Ben c'est une connection UDP donc je n en ai pas besoin, connect et listen c est pour TCP..

Reply

Marsh Posté le 25-03-2006 à 18:19:40    

a moins que je n'ai rien compris a UDP..:S

Reply

Marsh Posté le 25-03-2006 à 18:20:31    

3°) ensuite on lit la socket client à l aide de recvfrom
 
----
errata, pour udp tu n a pas besoin de connect côté client, c est juste sendto(...)

Reply

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

si si tu as besoin quand même de listen pour udp


Message édité par nargy le 25-03-2006 à 18:21:29
Reply

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

C est bon ArthurDent a trouvé: c'est *fromlen = sizeof(*son_s);
au lieu de *fromlen = sizeof(son_s);  
 
Il fallait avoir l'oeil! En tout cas merci pour ton aide nargy:)
 
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?

Reply

Marsh Posté le 25-03-2006 à 18:26:34    

killall udpser : ça tuera les eventuels serveurs qui sont encore en execution, meme si c'est bizarre que cela arrive

Reply

Marsh Posté le 25-03-2006 à 18:26:58    

non t a raison pour udp tu faire directement recvfrom

Reply

Marsh Posté le 25-03-2006 à 18:29:21    

c est SO_REUSEADDR à mettre en flag de bind.
 
man 7 socket:

Citation :


SO_REUSEADDR
              Indicates that the rules used in validating  addresses  supplied
              in  a  bind(2)  call  should allow reuse of local addresses. For
              PF_INET sockets this means that a socket may bind,  except  when
              there  is  an active listening socket bound to the address. When
              the listening socket is bound to INADDR_ANY with a specific port
              then  it  is  not  possible  to  bind to this port for any local
              address.


Reply

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

sans SO_REUSEADDR, les ports utilisés sont invalidés pendant un certain temps (même si aucun processus n écoute sur le port) ce qui peut poser problème pour un serveur.

Reply

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

mais il n y a pas d arguments dans le bind():
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
 
A moins que tu en utilise un autre, moi c'est le seul pour les socket que j ai trouvé.
 
Si c est bien dans celui la que tu mets le flag, tu le mets ou?

Reply

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

pardon je suis vraiment à l ouest aujourd hui:
 

Code :
  1. int setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen);

Reply

Marsh Posté le 25-03-2006 à 19:06:28    

ok je vois , merci pour ton aide :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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