CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[sockets C] envoyer plusieurs 'int'

delafayette
delafayette
Niveau 10
12 décembre 2007 à 09:30:02

Bonjour,
J´ai actuellement créé un serveur multiclients à l´aide de
select() mais j´ai aussi un problème pour envoyer des int au serveur. Pour mon chat multiclients, il n´y avait pas trop de problèmes, je n´avais que des char à envoyer.
Mais maintenant que je veux envoyer des int, ça se complique!
J´utilise donc sprintf() et atoi(). Jusque là, pas de trop gros problèmes... Mais j´ai décidé de créer un petit programme fenêtre avec la SDL où chaque joueur peut déplacer son perso à l´écran et voit celui des autres bouger. Ca devrait donc donner:

initialisation des variables

si(le joueur bouge en x)
--> alors pJoueur.x++ ou --
conversion de la valeur en char
envoi au serveur
(le serveur le renverra aux autres clients qui le convertiront en int

si(le joueur bouge en y)
--> alors pJoueur.y++ ou --
conversion de la valeur en char
envoi au serveur

J ai donc essayé, mais le serveur ne sait pas reconnaitre quand il reçoit les chars si c´est pJoueur.y ou pJoueur.x qu´il reçoit!
C´est à dire que par exemple:
1) je bouge le perso en x
2) le serveur envoie la position en x aux autres clients
3) je bouge le perso en y
4) /!\ le serveur l´interprete comme position en x et donc fait changer la position en x de mon perso chez les autres clients au lieu de la changer en y!

Et voilà donc mon problème. Comment puis-je faire différencier les deux variables à mon serveur? J´espère avoir été assez clair, et j´espère que ma question n´est pas trop stupide :o)
Il faut dire que je suis débutant aussi ^^

Merci d´avance pour vos réponses!

Fvirtman
Fvirtman
Niveau 10
12 décembre 2007 à 09:52:52

A toi de te créer un protocole :)
C´est a dire un format logique dans lequel tu envoies tes données.

De plus, je te déconseilles d´envoyer trop de paquets :
Dans ce que tu dis, tu envoies un x, puis tu envoies un y.
Donc tu envoies 2 fois 4 octets, et a chaque fois, tu y colles donc une trame TCP/IP qui fait 10 fois cette taille la. (je ne sais plus exactement la taille de la trame)

Si tu ne veux pas te casser la tete, envoie tout :
Un truc simple, bourrin, mais avec quelques restrictions :

struct Paquet
{
int x[50];
int y[50];
char truc[50];
double machin[10];
};

--> Tout ce que tu veux "transmettre" dans cette structure. Attention, il faut que ce soit réellement dans la structure : tableau statiques, pas de pointeurs.

Et ensuite, il te suffit d´envoyer la structure mise a jour, et, chez le client, de la recevoir dans une structure définie pareillle.

Inconvénients : ne marchera pas sur des processeurs Big Endian (mac & Unix) (mais marchera sous Windows et Linux)
Risque de probleme si tu es sur un systeme 32 bits et ton client sur un systeme 64 bits. ou vice versa

Voila, ça c´est une solution "simple", sinon, il faut que tu te fasses ton propre protocole : en disant que si ton paquet commence par un "1" alors ça veut dire que tu attends cette donnée d´abord, s´il commence par un "2", celle la... etc etc...

dnob700
dnob700
Niveau 10
12 décembre 2007 à 10:37:23

Quand select se débloque, il te renvoie le socket sur lequel tu peut lire. Tu peut te servir de son identifiant pour savoir de quel client il s´agit (une bonne méthode serait de regarder dans une table de hashage, mais c´est plus simpleen C++).

Pour ce qui est de l´envoie de données, tu peut envoyer tes int directement sur le réseau avec write :
int xy[2];
write(server,xy,sizeof(int)*2);

bien sûr, il faut que le serveur s´attende à recevoir juste deux entier et pas autre chose.
Tu peut même améliorer les choses en faisant un hton sur tes ints avant l´envoie et un ntoh après leur récépetion par les clients (si le serveur n´a pas besoin de les lire, alors il peut les garder en ordre network). Et enfin, un int fait toujours 4 octets quel que soit le processeur aujourd´hui (32 ou 64 bit, sur un 16 là je ne sais pas). Donc avec cette méthode, ça marche partout quel que soit le processeur ou la plateforme.

godrik
godrik
Niveau 30
12 décembre 2007 à 10:53:42

Attention fvirtman,
faire deux appels a write ne veut pas dire que l´on envoie deux paquets TCP. Le système est responsable de la formation des paquets et il est probable qu´il n´envoie pas le paquet immédiatement. Il doit y avoir un timeout ou qqch du genre.
Donc si son programme n´attends pas de réponse pour envoyer la suite, il n´enverra probablement qu´un seul paquet.

delafayette
delafayette
Niveau 10
12 décembre 2007 à 13:11:37

Merci pour vos réponses :)

fvirtman: si tu veux j envoie pas tout en même temps.
Quand le joueur appuie sur la fleche haut ou bas, la position.x change et ça l´envoie seulement dans ce cas là...
Sinon, je peux pas envoyer de pointeurs? Faut absolument passer par un int?

dnob700: Tu as résolu une partie de mon problème.
Si je récupère l´identifiant du socket, je peux faire la différence entre:
positionJoueur1.x et positionJoueur2.x, mais ça ne va pas pour autant faire la différence entre positionJoueur1.x et positionJoueur1.x, non?

sinon pour write() vaut mieux pas que je l´utilise puisque le serveur envoie la position uniquement quand il en reçoit une, cest à dire quand un joueur bouge (et donc lui envoie ses coordonnées)

godrik
godrik
Niveau 30
12 décembre 2007 à 13:25:06

Tu ne peux pas envoyer un pointeur. Enfin, tu peux l´envoyer, mais il n´a pas de sens pour la machine qui va le recevoir
en effet, il n´y a aucune raison que les informations soient structuré en mémoire de la même façon entre deux ordinateurs différents.

dnob700
dnob700
Niveau 10
12 décembre 2007 à 20:12:58

tu peut par exemple quand tu fait ton sprintf utiliser la chaine "x%d" ou "y%d" plutôt que juste "%d" et comme ça, le client regarde le premier caractère, si c´est x, alors il sait que c´est la coordonnée x et de même pour y. Tu peut envoyer autant de donnée que tu veux, donc ton problème n´est pas très complexe.

delafayette
delafayette
Niveau 10
13 décembre 2007 à 20:00:16

Pas bête, merci :)

Fvirtman
Fvirtman
Niveau 10
14 décembre 2007 à 00:42:34

C´est vrai qu´il y a un algo dans les cartes réseau qui groupe les paquets s´ils ne sont pas encore partis, donc 2 int envoyés rapidement ont de grandes chances d´etre envoyés en meme temps :)

Y´avait un nom pour cet algo, je ne sais plus lequel ! Mais il est cablé, il me semble dans les cartes réseaux non ?

godrik
godrik
Niveau 30
14 décembre 2007 à 11:11:27

Les cartes réseaux font des trucs comme ca, grouper deux paquets IP dans la meme trame ethernet ou peut etre meme fusionner des paquets IP. Mais c´est surtout ton système qui est responsable de cela.

blascowvitch
blascowvitch
Niveau 10
23 janvier 2008 à 21:40:08

Bonsoir,
Je sais que je fait un UP de plus ou moins un mois.

Mais j'aimerai vous signalez qu'en C on dispose des méthodes setsockopt() et getsockopt().

Elle permette de paramétrer la socket comme bon vous sembles.

Comme par exemple définir la taille du buffer de réception ou d'émission, permettre plusieurs binding sur le même port, rejoindre un groupe multicast, etc.

Si cela vous interresse je peux vous fournir plus de détail sur la fonction setsockopt...

Bien à vous ;)

godrik
godrik
Niveau 30
24 janvier 2008 à 01:09:26

tiens, je ne connaissais pas.
Je regarderais a l'occasion.
pour info c'est standardisé comme bestiau ? les memes options sont défini (et interprétées de la meme facon) sous windows et macos ?

blascowvitch
blascowvitch
Niveau 10
24 janvier 2008 à 19:37:28

Bonsoir,

Sous windows le fonctionnement des sockets est particulié.Mais un environnement de développement comme DEVc++ vous permet de faire de la programmation TCP/IP "linuxienne" ( et donc utilisé les fonctions setsockopt et getsockopt ) sous Windows.

Vous pouvez dans le monde unix aussi utilisez des fonctions comme fcntl et ioctl qui de manière générale prennent en paramètres un descripteur de fichier ou de socket, une requête et un argument de requête.

Bien à vous ;)

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Internet
  • Macintosh
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment