[C/Reseau] Petite explication niveau sockets please...

Petite explication niveau sockets please... [C/Reseau] - C++ - Programmation

Marsh Posté le 09-09-2002 à 03:07:59    

Je dois faire une relation client/server en C, pour l'instant ca se limite a :
 
Je lance le serveur qui attend un paquet.
 
Je lance le client qui balance un paquet au serveur pour dire bonjour et lui filer son IP dedans.
 
Le serveur envoie un paquet de confirmation au client.
 
Je vais donc avoir besoin de sockets pour faire ca...
 
J'ai declare deux sockets pour le client ( Un pour envoyer, un pour recevoir ) et deux pour le serveur ( idem).
 
Ma question est :  
 
-On peut utiliser un meme socket pour envoyer/recevoir des paquets ?
 
-Si je lance le serveur et le client sur la meme becane, ca fera 4 sockets sur le meme port... c'est pas un peu beaucoup ?
 
Pour l'instant, le client envoie un paquet au serveur. Ce dernier le recoit bien, et envoie son paquet de confirmation... mais le client le recoit jamais :/
 
D'ou mes questions sur les sockets...
 
Ah vi, si on a un paquet, on peux connaitre l'IP de l'envoyeur, meme si elle n;est pas dans le "contenu" du paquet ?
 
Merci ;)


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 09-09-2002 à 03:07:59   

Reply

Marsh Posté le 09-09-2002 à 08:50:40    

faut pas ouvrir 4 sockets !
 
seulement un de chaque coté:)
si t en mets plusieurs sur un même port, ca porte un autre nom ;)
 
si ton paquete de "retour" ne fait juste que confirmer, alors c pas la peine, suffit d'utilier des socket TCP, et t'aura le meme resultat.
 
l'IP de l envoyer est dnas le paquet :),
si tu l enleve ou si tu la changes, spa bien;)


Message édité par slvn le 09-09-2002 à 08:51:09
Reply

Marsh Posté le 09-09-2002 à 10:06:40    

- Une socket (y compris en TCP), ca marche dans les 2 sens. Inutile d'en créer 2 sur le client.
Pour le serveur, c'est un peu différent. Tu crées une socket particulière, qui se met en attente de connexion (ton appli reste bloquée à ce moment là. A toi d'en tenir compte). Dès qu'une connexion arrive (un client qui cherche à se connecter), la fonction dans laquelle tu étais bloqué retourne un résultat, qui est une nouvelle socket, connectée chez le client. Tu communiques donc avec le client sur cette nouvelle socket, et tu peux remettre la première socket en attente, au cas où un nouveau client arrive.
 
- Pour le serveur, tu dois fixer le numéro de port (faut bien que le client sache où s'adresser). Par contre, pour le client, c'est inutile. Tu peux laisser le système trouver un port disponible tout seul.
 
- Quand une socket est connectée, on peut connaître l'IP/port de celui qui est de l'autre côté (je parle de socket connectées, c'est à dire en TCP. En UDP, c'est différent).
 

Reply

Marsh Posté le 09-09-2002 à 10:20:40    

Salut,
 
Je me débrouille pas mal en client/serveur en C (si moi je dis ça, et bien !).
Si tu veux une aide dévouée :) , mail moi (juju-le-barbare@fr.fm)
 
@++


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 09-09-2002 à 18:31:15    

ah vi, je dois absolument utiliser les sockets UDP...
 
Donc en gros, 2 sockets de chaque cote ca sert a rien ? je vais tester...


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 09-09-2002 à 18:36:54    

Arf, quand je mets 2 sockets differents, le bind marche bieng.
 
Si j;utilise le meme, le bind passe pas...
 
Donc y en faut bien 2 differents non ?


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 09-09-2002 à 18:55:03    

d'ailleurs, en clair, il sert a quoi le bind...
 
:heink:
 
Pourquoi il en faut un avant de recevoir et pas avant d'envoyer...
 
bon, j'ai pondu ca :
 
server.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #define MYPORT 4950    // the port users will be connecting to
  12. #define MAXBUFLEN 100
  13. typedef struct {
  14.   int packet_ID;
  15.   int client_ID;
  16.   struct in_addr client_IP;
  17.   int client_port;
  18. } pack;
  19. int main(int argc, char *argv[])
  20. {
  21.   int sockfd;
  22.    int sockfd2;
  23.   struct sockaddr_in my_addr;    // my address information
  24.   struct sockaddr_in their_addr; // connector's address information
  25.   struct hostent *he;
  26.   struct hostent *me;
  27.   int addr_len;
  28.   pack p,p2;
  29.  
  30.   my_addr.sin_family = AF_INET;         // host byte order
  31.   my_addr.sin_port = htons(MYPORT);     // short, network byte order
  32.   my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
  33.   memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
  34.  
  35.  
  36.   if (argc != 2) {
  37.     fprintf(stderr,"usage: client hostname \n" );
  38.     exit(1);
  39.   }
  40.  
  41.   if ((me=gethostbyname("localhost" )) == NULL) {  // get the host info
  42.     perror("gethostbyname" );
  43.     exit(1);
  44.   }
  45.  
  46.   if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  47.     perror("socket" );
  48.     exit(1);
  49.   }
  50.  
  51.   if ((sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  52.     perror("socket" );
  53.     exit(1);
  54.   }
  55.   // attente de paquet
  56.   if (bind(sockfd2, (struct sockaddr *)&my_addr,
  57.    sizeof(struct sockaddr)) == -1) {
  58.     perror("bind" );
  59.     exit(1);
  60.   }
  61.  
  62.   addr_len = sizeof(pack);
  63.   if ((recvfrom(sockfd2, &p2, MAXBUFLEN-1 , 0,
  64.  (struct sockaddr *)&their_addr, &addr_len)) == -1) {
  65.     printf("ca a merde\n" ); 
  66.     perror("recvfrom" );
  67.     exit(1);
  68.   }
  69.   if (p2.packet_ID == 121)
  70.     {
  71.       their_addr.sin_family = AF_INET;     // host byte order
  72.       their_addr.sin_port = htons(p2.client_port); // short, network byte order
  73.       //      their_addr.sin_addr = *((struct in_addr *)&(p2.client_IP));
  74.       their_addr.sin_addr = *((struct in_addr *)me->h_addr);
  75.       memset(&(their_addr.sin_zero), '\0', 8);  // zero the rest of the struct
  76.       // Confirmation Packet
  77.       p.packet_ID = 131;
  78.       p.client_ID = 0;
  79.       p.client_IP = *((struct in_addr *)me->h_addr);
  80.       p.client_port = MYPORT;
  81.      
  82.       if ((sendto(sockfd2, &p, sizeof(pack), 0,
  83.    (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
  84.         perror("sendto" );
  85.         exit(1);
  86.       }
  87.       printf("paquet envoye\n" );     
  88.      
  89.     }
  90.   close(sockfd);
  91.   close(sockfd2);
  92.  
  93.   return 0;
  94. }


 
Client.c

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #define MYPORT 4950    // the port users will be connecting to
  12. #define MAXBUFLEN 100
  13. typedef struct {
  14.   int packet_ID;
  15.   int client_ID;
  16.   struct in_addr client_IP;
  17.   int client_port;
  18. } pack;
  19. int main(int argc, char *argv[])
  20. {
  21.   int sockfd;
  22.   int sockfd2;
  23.   struct sockaddr_in my_addr;    // my address information
  24.   struct sockaddr_in their_addr; // connector's address information
  25.   struct hostent *he;
  26.   struct hostent *me;
  27.   int addr_len;
  28.   pack p,p2;
  29.     my_addr.sin_family = AF_INET;         // host byte order
  30.     my_addr.sin_port = htons(MYPORT);     // short, network byte order
  31.     my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
  32.     memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
  33.   if (argc != 2) {
  34.         fprintf(stderr,"usage: client hostname \n" );
  35.         exit(1);
  36.     }
  37.  
  38.     if ((he=gethostbyname(argv[1])) == NULL) {  // get the host info
  39.         perror("gethostbyname" );
  40.         exit(1);
  41.     }
  42.     if ((me=gethostbyname("localhost" )) == NULL) {  // get the host info
  43.         perror("gethostbyname" );
  44.         exit(1);
  45.     }
  46.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  47.         perror("socket" );
  48.         exit(1);
  49.     }
  50.     if ((sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  51.         perror("socket" );
  52.         exit(1);
  53.     }
  54.     their_addr.sin_family = AF_INET;     // host byte order
  55.     their_addr.sin_port = htons(MYPORT); // short, network byte order
  56.     their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  57.     memset(&(their_addr.sin_zero), '\0', 8);  // zero the rest of the struct
  58.     // Registration Packet
  59.     p.packet_ID = 121;
  60.     p.client_ID = 0;
  61.     p.client_IP = *((struct in_addr *)me->h_addr);
  62.     p.client_port = MYPORT;
  63.    
  64.     if ((sendto(sockfd, &p, sizeof(pack), 0,
  65.       (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
  66.         perror("sendto" );
  67.         exit(1);
  68.     }
  69.     printf("paquet envoye\n" );
  70.     // attente du paquet de retour...
  71.        if (bind(sockfd2, (struct sockaddr *)&my_addr,
  72.      sizeof(struct sockaddr)) == -1) {
  73.       perror("bind" );
  74.       exit(1);
  75.       }
  76.     addr_len = sizeof(pack);
  77.     if ((recvfrom(sockfd, &p2, MAXBUFLEN-1 , 0,
  78.  (struct sockaddr *)&their_addr, &addr_len)) == -1) {
  79.       printf("ca a merde\n" ); 
  80.       perror("recvfrom" );
  81.         exit(1);
  82.     }
  83.    
  84.     close(sockfd);
  85.     close(sockfd2);
  86.    
  87.     return 0;
  88. }


 
Vous me dites c'est du bidouillage je vous reponds ouiiiiiiiiiiii ;)
 
Mais bon, avec ca, le server attends son paquet, je lance le client qui envoie son paquet, le server le recoit et trouve le bon contenu, envoie le sien... que le client recit jamais :/
 
Vous pouvez m'expliquer ?
 


Message édité par Tetedeiench le 09-09-2002 à 19:11:23

---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 09-09-2002 à 20:06:30    

beng ?
 
Chuis vraiment bloqued la :/


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 09-09-2002 à 21:37:05    

c quoi le pb en fiat ?!
 
t as bien initialise les structures  sockaddr ?!
 -> ou ca pose pb ?
   a la creation du socket ? au bind ? au send ? au recv ?

Reply

Marsh Posté le 09-09-2002 à 23:49:00    

Hum, perso, en UDP j'ai toujours ouvert 2 sockets sur le client et 2 sur le serveur.Ca marchait bien et je crois pas que tu puisse faire autrement.
 
Cependant, en TCP je te confirme qu'une seule socket (c masculin ou féminin je sais jamais) sur le client suffit et 2 sur le serveur (1 socket de rendez-vous où le client se connecte au début, et 1 socket par client). En TCP une socket marche dans les 2 sens.
 
En UDP, je suis pas sûr !

Reply

Marsh Posté le 09-09-2002 à 23:49:00   

Reply

Marsh Posté le 09-09-2002 à 23:56:30    

arf, j'ai un doute, mais je crois que j'ai jamais fait 2 socket en udp....
 
server : create -> bind -> recvfrom/sendto                  
client : create -> recvfrom/sendto    
 
pour ton socket udp, tu mets :  
AF_INET, SOCK_STREAM, IPPROTO_TCP comme para ?!  
       

Reply

Marsh Posté le 10-09-2002 à 00:28:37    

nop !
 
Ya toujours qu'un seul socket de chaque coté !
Ces 2 sockets forment un seul tube de communication (connecté ou non selon que c'est TCP/UDP)
 
Si tu veux créer plusieurs sockets, c'est éventuellement du côté serveur TCP, qui lorsqu'il reçoit une connection d'un client créé une socket puis fork le processus, et pendant ce temps le père se remet en écoute (on peut définir le nombre maxi de clients dans l'appel à listen())
N'oublie pas select() si tu veux autoriser plusieurs clients.
 
@++


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 10-09-2002 à 02:56:09    

ouiiiiiiiii merci ca maaaaaaaaaarche :love:
 
Je reviendrai surement poser des questions, mais l;echange de paquets fonctionne enfin :love:


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 10-09-2002 à 10:02:02    

Tetedeiench a écrit a écrit :

ah vi, je dois absolument utiliser les sockets UDP...
 
Donc en gros, 2 sockets de chaque cote ca sert a rien ? je vais tester...



En UDP, c'est différent. Tu n'as pas la notion de connexion.
Dans ce cas, une seule socket suffira côté serveur. Elle recevra les paquets de tous les clients, et tu peux regarder pour chacun d'eux d'où il vient (pratique si tu veux envoyer une réponse).
 
UDP respecte les limites des paquets. C'est à dire que si un client envoie un paquet de 149 octets, le serveur recevra d'un seul bloc les 149 octets. Où ne recevra rien du tout.
Il n'y aucun engagement sur le fait que le paquet ait été reçu. C'est à toi de mettre en place un dispositif d'accusé réception si tu as besoin d'être sur que la paquet est bien arrivé à destination (contrairement à TCP).
 
Pour le bind, ce n'est pas obligatoire. Tu t'en sert si tu veux que ta socket soit sur un port déterminé. Sinon, c'est l'OS qui te la met où il veut.

Reply

Marsh Posté le 10-09-2002 à 15:39:08    

Tetedeiench a écrit a écrit :

ouiiiiiiiii merci ca maaaaaaaaaarche :love:
 
Je reviendrai surement poser des questions, mais l;echange de paquets fonctionne enfin :love:




 
ben dis nous plutôt ce que tu as fait pour que ça marche ;)


---------------
Du temps à perdre ? -> http://www.juju-le-barbare.fr.fm
Reply

Marsh Posté le 10-09-2002 à 17:38:39    

mrbebert a écrit a écrit :

En UDP, c'est différent. Tu n'as pas la notion de connexion.
Dans ce cas, une seule socket suffira côté serveur. Elle recevra les paquets de tous les clients, et tu peux regarder pour chacun d'eux d'où il vient (pratique si tu veux envoyer une réponse).
 
UDP respecte les limites des paquets. C'est à dire que si un client envoie un paquet de 149 octets, le serveur recevra d'un seul bloc les 149 octets. Où ne recevra rien du tout.
Il n'y aucun engagement sur le fait que le paquet ait été reçu. C'est à toi de mettre en place un dispositif d'accusé réception si tu as besoin d'être sur que la paquet est bien arrivé à destination (contrairement à TCP).
 
Pour le bind, ce n'est pas obligatoire. Tu t'en sert si tu veux que ta socket soit sur un port déterminé. Sinon, c'est l'OS qui te la met où il veut.




 
tout à fait d'accord !  :jap: Je m'en rapelle jamais, mais c'est ca !

Reply

Marsh Posté le 11-09-2002 à 04:50:04    

juju-le-barbare a écrit a écrit :

 
 
ben dis nous plutôt ce que tu as fait pour que ça marche ;)




 
j'ai tout repris a zero.
 
En bidouillant un seul socket de chaque cote, et en ne bindant QUE du cote server.
 
Chai pas pkoi, mais ca amrche d'enfer ;)
 
Me reste a threader le bordel et zouuuu, project closed :sol:
 
Va falloir que je demande au prof aussi comment il envoie un entier dans un paquet... de telle sorte qu;il soit lisible par n'importe quelle becane, que ce soit un Sparc qu'un RISC ou un CISC...
 
Car la, en changeant d'archi, ca merde legerement :/


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 11-09-2002 à 09:39:23    

regarde les fonction ntohl et htonl :
- htonl convertit un long au format 'network'
- ntohl convertit du format network au format local utilisé par la machine
http://search.microsoft.com/gomsur [...] tohl_2.asp
 
De même, tu as htons pour les entiers sur 2 octets.
 
Edit : ce lien là est mieux :
http://search.microsoft.com/gomsur [...] dering.asp


Message édité par mrbebert le 11-09-2002 à 09:40:46
Reply

Sujets relatifs:

Leave a Replay

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