Questions souvent posées (FAQ)

Voir le sujet précédent Voir le sujet suivant Aller en bas

Questions souvent posées (FAQ)

Message  -ed- le Mer 28 Mai 2008 - 2:46

Je voudrai savoir si c'est possible (par exemple) d'envoyer un entier directement via la fonction send(), comme ceci:
Code:

long int len_file = ...truc...
send(sock, &len_file, sizeof(long int), 0);
Car ça me met un warning:
warning: passing arg 2 of `recv' from incompatible pointer type.
Mais j'ai remarqué que ça le prend quand même.

Le transfert direct de valeurs numériques est déconseillé car ce n'est pas du tout portable.

http://mapage.noos.fr/emdel/notes.htm#enreg_struct

Même si le contexte semble différent, il est similaire (usage de flux d'octets).

Je te conseille de lire cet article et de poser des questions si tu ne comprends pas. Je recommande la solution 'texte'.

Bon donc apparemment si je fais un transfert direct de valeurs numériques je peux perdre en portabilité (selon la machine?).

J'ai rapidement lu votre doc, mais je ne comprends pas trop la chose, dans mon cas, je veux envoyer un 'long int' par exemple:
Je dois alors définir un format de données indépendant sous forme de texte, apparemment ...

Dans la doc il est dit que, pour les fichier:
"Il nécessite une conversion à l'écriture (host->file) et une conversion à la lecture (file->host)"

Donc dans le contexte de mon cas, avant d'envoyer sur le réseau mon "long int", je dois le transformer de (host->truc) et à la réception de l'autre coté je le retransforme en (truc->host) ...

Alors en cherchant sur le lien que vous proposez à la fin de votre article sue la programmation réseau (http://www.chez.com/vidalc/lf /socket.html)
J'ai lu qu'il faut (pour garder le portage) mettre les octets dans l'ordre "Network Order" avant de les envoyer sur le réseau... càd:

Convertir en 'Network Byte Order' avant d'envoyer sur le réseau ( ex: avec htonl() ) et le reconvertir en 'Host Byte Order' après l'avoir reçu de l'autre coté ( ex: avec ntohl() ).

Donc: à l'écriture (host->network) et à la lecture (network->host).

Car selon ce que j'ai du comprendre: sur certain processeur l'rodre des octets n'est pas le même..., donc si le code doit tourner sur une machine qui n'a pas le même 'Byte Order' , on dois utilisé ces fonctions de conversion ...

Ensuite, je suppose qu'avec ces fonctions, la machine gère la chose, elle sait elle-même comment elle est par rapport au 'Network Byte Order' ... et en cherchant encore un peut plus, j'ai trouvé que le type que je dois spécifier à la place de mon long int est uint32_t ou uint16_t , c'est quoi ces type ?

Je te conseille d'oublier les formats binaires pour le moment. Comme je l'ai indiqué, une solution simple consiste à transférer les valeurs numériques sous forme textuelle :
Code:

int x = 1234;

char data[32];
sprintf (data, "%d\n", x);

int sent = send (sock, data, strlen (data), 0);
La chaine "1234\n" est transmise caractères par caractères. A la réception :
Code:

char data[32];

int recvd = recv (sock, data, sizeof data - 1, 0);

if (recvd > 0)
{
  data[recvd] = 0;
  char *pend;
  int x = strtod (data, &pend, 10);

  if (*pend == '\n')
  {
      printf ("x = %d\n", x);
  }
}
La portabilité n'est perdu qu'entre 2 systems d'exploitation différent, n'est ce pas ?

Si une structure est envoyé d'un Windows XP à un Windows XP, est ce que le destinataire sera en mesure de reconstituer la structure ?

C'est plus subtil que ça. Ça peut changer si les machines sont différentes, les systèmes sont différents, les compilateurs sont différents, les options de compilation sont différentes.

Bref, c'est pas simple, et c'est pourquoi le transfert direct en binaire est fortement déconseillé. Il existe des formats binaires standards (BER, XDR), mais leur mise en œuvre est complexe. Le plus simple et le plus portable, comme maintes fois répété, est le format texte.

Et il n'existe pas une solution simple de transmettre une structure d'un PC à un autre ?

1 - C'est pas si compliqué, fais toi une fonction ou une macro qui effectuera la conversion pour toi, l'avantage est que tu codes une fois la fonction et ensuite pour toi c'est transparent, c'est comme si tu envoyais la structure.

2 - Le mode texte. (CSV, par exemple).

Désolé d'insister mais je ne trouve vraiment pas ça simple de devoir passer par du texte.

Je suis désolé que tu trouves ça compliqué, mais il n'y a pas de moyens portable plus simple.

Et je trouve gênant de devoir envoyer plus de données pour obtenir le "même" résultat.

Quelque soit la méthode, il y a des transformations à faire pour être portable.

Est ce qu'on pourrait se permettre, dans le cas d'un jeu en réseau non libre et compilé une unique fois qui ne tournerait que sous Windows d'utiliser l'envoi de structures ?

C'est techniquement possible, mais ce n'est pas portable. Au moindre changement dans la chaine de développement, le mécanisme risque de ne plus fonctionner.

Maintenant que tu connais les risques et les enjeux, tu fais tes choix. Je me contente de donner des conseils de professionnel.

Je vais donc chercher du côté "CSV".
Histoire de continuer le sujet : C'est quoi cette bête là ?


Comma Separated Values

Il y a différent formats. Le plus simple est

<champ>[;<champ>[; <champ>[*]]]EOL

Les champs numériques sont généralement codés en décimal. Par exemple :

Nom, prénom, age

"Delahaye;Emmanuel;50\n "

(Sans espaces.)

Comma-separated_values

Il existe une librairie pour faciliter les conversions ou bien on est obligé de se coder ses propres fonctions ?

1 - Non bien sur, il existe une même plusieurs librairie qui permettent l'utilisation du format CSV, la plus connue est libcsv.

2 - Je n'en connais pas, et je suis en général assez content d'utiliser mes propres fonctions (c'est mon coté artisan...), mais ça existe peut être...




J'aimerais savoir faire un chat comme MSN.

Microsoft utilise le protocole (propriétaire attention à la licence) MSNP (MicroSoft Notification Protocol) pour son msn messenger. Voir cette page [url=http://en.wikipedia.org/wiki/]Microsoft_Notification_Protocol[url]
et entre autres l'avant dernier lien.

Il existe des 'clones' sous Linux... (aMSN, pidgin (ex-gaim) ...)

http://amsn.sf.net/
http://www.pidgin.im/

J'imagine que les serveurs d'MSN ne font que transmettre quelques informations sur le compte des clients. Cela doit permettre au client de savoir à quel adresse se situe actuellement leurs contacts.

C'est d'ailleurs sans doute sur ce principe que le transfert de fichier peut s'affectuer sans passer par les serveur. Tout comme les logiciels de P2P j'imagine.

Mais alors comment ça fonctionne ?

Une fois que le client est connecté au serveur, il demande l'adresse IP de chacun de ses contacts et peut s'y connecter ?

Le problème, c'est que ces clients (contacts) ne sont pas à l'écoute.

J'en viens à ma question : comment établir une connexion entre deux clients sans mettre de port à l'écoute grâce uniquement au données fournies par le serveur de comptes ?

L'idée, ce serait de créer un petit logiciel de partage de fichiers entre les membres de mon Forum sans passer par un serveur.

Pour ceux qui serait intéressé, je viens de tomber sur un Wiki très intéressant :
http://fr.wikipedia.org/wiki/Gnutella

C'est tout le principe du réseau décentralisé Gnutella. Dommage qu'il y ait encore ce GWebCache mais ça, on ne pourra jamais s'en passer.

Ce n'est pas un problème de protocol, je cherche à comprendre comment sont fait les logiciel qui décentralisent l'envoi d'informations.

Le problème se situe au niveau de la connexion d'un client à un autre client.

Le serveur ne doit servir qu'a informer les clients de leurs existences.

Les sockets utilisent uniquement les connexions client/serveur. Pour réaliser une connexion client/client, on passe obligatoirement par un serveur qui fait le 'relais'. Il n'y a pas d'alternative.

Client A <--> serveur <--> Client B

Je doute vraiment de ce que tu dis.

Je suis tombé plusieurs fois sur des choses qui m'indique le contraire.

Notament http://fr.wikipedia.org/wiki/C TCP et http://fr.wikipedia.org/wiki/D irect_Client-to-Client .

Et par exemple, sur MSN, on peut voir qu'une connexion s'établie avec l'autre client lors de la demande d'envois d'un fichier (avec aports.exe). Et aucun port se met à l'écoute d'un client. C'est ça qui est étonant.

Donc, apparemment, il faut un serveur pour s'y connecter mais après avoir connecté plusieurs clients sur ce serveur, il semblerait qu'il soit possible d'échanger des informations directement d'un client à un autre sans même passer par le serveur.

Et ça expliquerait peut-être pourquoi les serveurs peuvent supporter autant de monde à la fois pour faire fonctionner Skype et d'autre logiciel du même type.

C'est d'ailleurs grâce à cette technique que les clients Gnutella parviennent à charger des fichiers d'autre clients en utilisant pleinement leur bande passante. Et le serveur GWebcache ne sature donc jamais. Il ne sert qu'à distribuer la liste des clients connecté actuellement.


Je crois qu'il y a confusion sur la définition de serveur.

S'agissant de connexion de type TCP/IP, une connexion client/client n'est pas possible. C'est forcément client/serveur.

Mais un serveur au sens TCP/IP n'est pas un serveur de données au sens 'architecture réseau'. C'est juste une façon, peut être confusante, de nommer un dispositif logiciel qui 'attend une connexion', par opposition au client qui est l'initiateur de l'action de connexion. Je rappelle le protocole :

1 - le serveur se met en mode attente de connexion (accept() : le thread serveur est suspendu)
2 - le client passe en mode demande de connexion (connect() : le thread client est suspendu)
3 - le serveur accepte la connexion. La fonction accept() se débloque, elle retourne un numéro de socket (nouveau client connecté) et confirme la connexion au client sur le réseau.
Le serveur peut envoyer un message d'accueil (send()) et se suspend avec la fonction recv() (attente de données)
4 - le client reçoit la confirmation de connexion : connect() se débloque et retourne OK.
Il peut envoyer une information par send()
Il se bloque en réception avec recv()

Chaque machine (client ou serveur) est maintenant capable d'émettre et de recevoir des données.

Rien n'empêche qu'un 'routage' (relais) soit effectué et que les données reçues d'un client A par le serveur, soient renvoyées à un client B (et inversement), sans que le serveur ne traite la moindre donnée... C'est ce qu'on appelle un "serveur transparent".

Il se peut que certains systèmes disposent de mécanismes permettant d'effectuer très rapidement et très automatiquement ce relayage de données (je n'ose pas parler de relayage de trame, quoique...) directement, au plus bas niveau, ce qui accélère et simplifie le traitement. Cela dépasse le simple usage des sockets.

C'est comme ça que fonctionne un chat, en créant une connexion client/client 'virtuelle'. (En réalité, c'est client/serveur transparent/client).

Mais je vais quand même lire les articles que tu m'as recommandés.

OK. Il s'agit de protocoles applicatifs niveau 5/6/7, rien à voir avec le niveau TCP/IP (3/4). On est pas dans le même domaine.

Effectivement, une connexion logique cli/res/cli permet de réaliser une connexion applicative cli/cli... Personne n'en doute !

Donc d'après toi, il n'est pas possible d'effectuer un transfert de fichier (ou autres données) de client à client sans consommer de BP sur un serveur.

Donc les logiciel de P2P comme LimeWire (qui on de très bon taux de transfert) utilise des serveurs qui on une très grande BP ?

Ça me parait surréaliste. Merci quand même.


Bah, ca dépend de quelle couche on parle...

[Complément]
Dans les protocoles P2P, les clients sont aussi serveurs. En fait, chaque utilisateur est un serveur... Un serveur est capable de créer une connexion avec un autre serveur dans un de ses threads...




Je suis débutant dans la programmation réseau mais j'ai quelques bases en ce qui concerne le C.
Donc si vous pouvez m'aider en m'expliquant ce qu'on pourra faire avec le librairie libnet et libpcap de C en ce qui concerne la programmation réseau.


libcap : Capturer des trames de bas niveau...

http://philippe.laval.free.fr/ Programmation/libpcap_libnet.php
http://www.google.fr/search?hl=fr&q=programmation+C+sniffer+libpcap&meta=lr%3Dlang _fr

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum