Question

J'ai un client et un programme de serveur où je veux envoyer un struct entier du client, puis sortie l'élément struct « ID » sur le serveur.

Je l'ai fait tout le relier etc et déjà réussi à envoyer une chaîne par:

send(socket, string, string_size, 0);

Alors, est-il possible d'envoyer un struct au lieu d'une chaîne par envoi ()? Puis-je remplacer juste mon tampon sur le serveur pour être un struct vide du même type et aller?

Était-ce utile?

La solution

Welll ... envoyer struct à travers le réseau est un peu difficile si vous le faites correctement.

Carl est juste - vous pouvez envoyer un struct à travers un réseau en disant:

send(socket, (char*)my_struct, sizeof(my_struct), 0);

Mais voici la chose:

  • sizeof (ma_struct) peut changer entre le client et le serveur. Compilateurs font souvent une certaine quantité de remplissage et de l'alignement, de sorte que si vous définissez l'alignement explicite (peut-être à l'aide d'un #pragma pack ()), cette taille peut être différent.
  • L'autre problème a tendance à être d'ordre d'octet. Certaines machines sont big-endian et d'autres sont peu endian, de sorte que l'arrangement des octets peuvent être différents. En réalité, à moins que votre serveur ou client est en cours d'exécution sur le matériel non-Intel (ce qui est probablement pas le cas), alors ce problème existe plus en théorie que dans la pratique.

Ainsi, les gens proposent souvent la solution est d'avoir une routine qui sérialise la struct. Autrement dit, il envoie le struct un membre de données à la fois, en veillant à ce que le client et le serveur envoie uniquement () et recv () le nombre spécifié exact d'octets que vous code dans votre programme.

Autres conseils

Les machines client et serveur « le même »? Ce que vous proposez ne fonctionnera que si les compilateurs C à chaque extrémité exposent la structure en mémoire exactement la même chose. Il y a beaucoup de raisons pour lesquelles cela peut ne pas être le cas. Par exemple, les macines client et serveur peuvent avoir des architectures différentes, la façon dont ils représentent des nombres dans la mémoire (grand-boutiste, petit-boutiste) pourrait différer. Même si les machines clientes et machine serveur ont la même architecture deux différents compilateurs C peuvent avoir des politiques différentes sur la façon dont ils exposent struct en mémoire (par exemple. Padding entre les champs pour aligner ints sur les limites de mots). Même le même conmpiler avec des drapeaux différents pourrait donner des résultats différents.

Pragmatique, je suppose que votre client et le serveur sont le même genre de machine et donc ce que vous proposez travaillerai, mais vous devez être conscient qu'en règle générale il ne sera pas et c'est pourquoi des normes telles que CORBA ont été inventés, ou pourquoi les gens utilisent une représentation générale tels que XML.

Vous pouvez, si le client et le serveur ont mis le struct exactement de la même manière, ce qui signifie que les champs sont de la même taille, avec le même rembourrage. Par exemple, si vous avez un long dans votre struct, qui pourrait être 32bits sur une machine et 64bits de l'autre, auquel cas le struct ne sera pas reçu correctement.

Dans votre cas, si le client et le serveur vont toujours être sur les implémentations très similaires C (par exemple, si cela est juste le code que vous utilisez pour apprendre quelques notions de base, ou si, pour une autre raison, vous savez que votre code ne jamais avoir à exécuter sur votre version actuelle de Mac OS X), alors vous pouvez probablement vous en sortir avec elle. Rappelez-vous que votre code ne fonctionnera pas nécessairement correctement sur d'autres plates-formes, et qu'il n'y a plus de travail à faire avant qu'il ne soit adapté à une utilisation dans la plupart des situations réelles.

Pour la plupart des applications client-serveur, cela signifie que la réponse est que vous ne pouvez pas le faire en général. Ce que vous faites est de définir le message en fonction du nombre d'octets envoyés, quel ordre, ce qu'ils veulent dire, et ainsi de suite. Ensuite, à chaque extrémité, vous faites la plate-forme spécifique à quelque chose à faire en sorte que la structure que vous utilisez a exactement la mise en page nécessaire. Même si, vous pourriez avoir à faire quelques octets swapping si vous envoyez des membres entiers de la struct little-endian, et vous voulez que votre code à exécuter sur une machine big-endian. formats d'échange de données comme XML, JSON et les tampons de protocole Google existent afin que vous ne devez pas faire ce genre de choses Checklist.

[Edit: rappelez-vous aussi bien sûr que certains membres de struct ne peuvent jamais être envoyés sur le fil. Par exemple, si votre struct a un pointeur, puis l'adresse se réfère à la mémoire sur la machine d'envoi et ne sert à rien à l'extrémité de réception. Toutes mes excuses si cela est déjà évident pour vous, mais il est certainement pas évident pour tout le monde quand ils commencent juste avec C].

Vous pouvez, mais vous devez être conscient de 2 choses importantes.

  1. Les programmes sur les deux extrémités doivent être ABI compatible. Ils sont généralement si les deux extrémités fonctionnent sur la même architecture de processeur, même système d'exploitation, compilé avec les mêmes drapeaux du compilateur et compilateur.
  2. TCP est un flux. Vous devez vous assurer que vous envoyez le tout struct. Regardez la documentation de l'appel send () - elle renvoie le n ° d'octets envoyés - qui pourrait être moins que vous avez dit à. Même du côté du récepteur. Tout simplement parce que vous avez envoyé le struct avec 1 Envoyer appel, ne signifie pas que vous la recevrez avec 1 appel recv. Il font prendre plusieurs appels recv pour obtenir toutes les pièces.

Oui, struct du même type sont de la même taille. Si vous obtenez votre coulée de pointeur droite vous êtes bon d'aller.

En général, il est une mauvaise idée de le faire, même si votre client et votre serveur se révèlent mettre la structure en mémoire de la même manière.

Même si vous ne comptez pas passer des structures de données plus complexes (qui impliquerait des pointeurs) avant et en arrière, je vous recommande de sérialiser vos données avant de l'envoyer sur le réseau.

Envoyez les données sous forme de fichier texte, puis le décoder après l'avoir reçu. Ceci est la meilleure façon si vous voulez que vos données comme !! envoyés

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top