maitretarot-devel-fr
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Maitretarot-devel-fr] nouveau protocole


From: Yves Mettier
Subject: Re: [Maitretarot-devel-fr] nouveau protocole
Date: Mon, 16 Dec 2002 23:24:44 +0100 (CET)

> Globalement, le truc le plus simple, c'est : en cours de jeu, le serveur
> envoie toutes les données (après que chaque joueur est joué) qu'il a
> avec un flag "à toi de jouer". Comme ça, il n'y a qu'un seul type de
> message.

T'es violent, toi.
Ca fait quasi 8k dans l'etat actuel des choses. Et tu voulais faire ca en
udp!?


>
> On mets un timeout sur la réponse, tu renvoie 2-3 fois, puis après tu
> envoie le paquets à tous avec un flags en "erreur". C'est ça le vrai
> stateless:)

On laisse tomber le stateless.
On va s'inspirer des rpc en fait.

> Il faut envoyer ses cartes restant, des flags (erreur ou pas, son tour
> de jouer ou pas,...), les plis (l'équipe du preneur puis l'autre), le
> paris, les annonces, tout quoi. 1 seul message avec l'état dedans
> (erreur ou pas, etc...)

Outre le fait qu'on laisse tomber le stateless, sachant qu'actuellement,
ca fait environs 8k et y'a pas de format, si on le formate, ca risque de
prendre encore plus!

Yves

>
> nicO
>
> On 16 Dec 2002 22:06:26 +0100
> philippe brochard <address@hidden> wrote:
>
>> Yves Mettier <address@hidden> writes:
>>
>> > On 16 Dec 2002 19:00:30 +0100
>> > philippe brochard <address@hidden> wrote:
>> >
>> > >
>> > > Bonjour a tous,
>> > >
>> > > suite a une discution avec Yves sur IRC, nous avons decider
>> > > de changer de protocole pour faire en sorte que la partie
>> > > gestion de l'ordre du jeu soit initiee par le serveur et
>> > > non pas dans le client (ou la lib client) comme c'est le
>> > > cas actuelement.
>> > >
>> > > Pour cela, voila la liste des fonctions dont ont besoin
>> > > les clients :
>> > >
>> > > Vocabulaire :)
>> > >   get : le client a besoin d'une information du serveur
>> > >   set : le client donne une valeur au serveur.
>> >
>> > Euh, vu que le client deviendra une sorte d'objet manipule par le
>> serveur, c'est plutot le contraire.
>> > Exemple: quand le serveur fait appel a get_hand_cards() du client,
>> il ne demande pas au client les cartes. Il fait le contraire: il les
>> fournit.
>> >
>> eh, eh, tout depend tu cote ou tu te place :)
>> mais, bon va pour le sens inverse.
>>
>> > D'autre part, get et set sont des mots generalement associes a des
>> variables. Or d'apres notre discussion, on ne travaille pas avec un
>> systeme de variables mais un systeme de commandes (on avait parle de
>> procedures a cause de l'analogie avec les rpc).
>> > Le vocabulaire devient donc du vocabulaire d'action, comme compute,
>> exec, init, etc.
>> >
>> ou get : prend   set : envoi/fixe
>> set_bid : le client donne son enchere
>> get_card : le client prend les cartes qu'il a en mains
>> (se sont des actions, non ?)
>>
>> > >
>> > >
>> > > Identification :
>> > > --------------
>> > >
>> > >   * {Nick, } set_identity_client (void)
>> > >
>> > >   Cette fonction est appele au debut pour realiser(?) la connexion
>> et informer le serveur sur le client qui vient de ce connecter.
>> Les parametres de version ne sont pas primordial pour le client
>> mais il peuvent etre utiles.
>> > >
>> > >
>> > >   * {void} get_resume_client (place, nombre_joueur, nick_client1,
>> > >       nick_client2, nick_client3, ..., score1, score2, score3,
>> ...)
>> > >
>> > >   Cette fonction permet d'informer le client sur les autres
>> > >   joueurs. la bornes nick_client3 depend du nombre de joueur, elle
>> peut aller jusqu'a nick_client5 dans le cas d'un jeu a 5 joueurs
>> ou nombre_joueur = 5.
>> > >   Les score1 a 3 (4 et 5) sont les scores totaux des precedentes
>> parties.
>> > >
>> > >
>> > > Debut du jeu :
>> > > ------------
>> > >
>> > >   * void get_hand_cards (c1, c2, c3, c4, ..., c18)
>> > >
>> > >   Le client recoit les cartes qu'il a en mains (c1, c2...).
>> > >   Le parametre c18 peut varier de c15 a c24 suivant un jeu a 5
>> joueurs
>> > >    ou 3 joueurs.
>> >
>> > 24 parametre.
>> > Si on est a 4, les 6 derniers seront undef. Si on est a 5, ce seront
>> les 9 derniers a etre a undef.
>> >
>> ok, j'ai laisse des ... pour ne pas rentrer dans le detail
>> du codage (on pouvais aussi utiliser des tableaux dynamiques,
>> ou fixer le nombre de parametre au depart, ou ...)
>>
>> > >
>> > >
>> > > Encheres :
>> > > --------
>> > >
>> > >   * {enchere} set_bid (e1, e2, e3, ...)
>> > >
>> > >   Cette fonction est appelee si le client doit faire une
>> > >   enchere.
>> > >   Le serveur lui fourni les encheres des autres joueurs
>> > >   (e1,e2,e3,e4,e5 enchere des clients 1 2 3 4 5 suivant le
>> > >   nombre de joueurs)
>> > >
>> > >
>> > >   * void other_bid (place, e1, e2, e3 , ...)
>> > >
>> > >   Cette fonction est appelee quand un autre joueur est en
>> > >   train de faire sont enchere. Le serveur fourni la place du
>> joueur qui est en train de faire sont enchere, ainsi que les
>> encheres deja faites.
>> > >
>> > >
>> > > Chien :
>> > > -----
>> > >
>> > >   * {c1, c2, ..., c6} set_chien (pc1,pc2,...,pc6)
>> > >
>> > >   Cette fonction est appellee si le client doit faire un chien
>> (petite ou garde).
>> > >   Le serveur fourni les cartes du chien original (pc1...pc6). Le
>> client renvoit les cartes du chien qu'il a fait (c1...c6). Les
>> parametres c6 et pc6 peuvent etres c6,pc6 pour un jeu a 3 ou 4
>> et c3,pc3 pour un jeu a 5 joueurs.
>> > >   Tant que le chien n'est pas valide, le serveur demande au client
>> de faire un chien.
>> > >
>> > >
>> > >   * void chien_valide (c1, c2, ..., c6)
>> > >
>> > >   Cette fonction est appellee si le chien fait par le client (avec
>> set_chien) est valide. Elle permet au client de savoir que le
>> serveur a accepte son chien.
>> > >
>> > >
>> > >   * void other_set_chien (place, c1, c2, ..., c6)
>> > >
>> > >   Cette fonction est appellee quand un autre joueur est en train
>> de faire son chien. Le serveur fourni la place du joueur qui est
>> en train de faire son chien et le chien original.
>> > >   Meme reflexion que precedement sur le parametre c6 suivant le
>> nombre de joueur. (Ceci toujours dans le cas d'une petite ou
>> d'une garde).
>> > >
>> > >
>> > >   * void no_chien (void)
>> > >
>> > >   Cette fonction est appellee si les clients n'ont pas a faire de
>> chiens(garde sans, garde contre).
>> > >
>> >
>> > Manque les annonces ici.
>> > Tu peux deja fournir le proto des procedures, voire les implementer,
>> meme si les arguments seront initialement ignores et une valeur
>> undef est renvoyee.
>> > J'ai vu que c'est plus bas dans le mail.
>> >
>> oui, je les ai misent plus bas parce que je ne me souvient plus
>> a quelle moment on les fais. de toute facon, c'est au serveur
>> d'apppeler la fonction annonce, le client y repondra quel que
>> soit le moment ou ca se passe, c'est le serveur qui impose l'ordre.
>>
>> > >
>> > > Jeu des cartes :
>> > > --------------
>> > >
>> > >   * {card} set_card (lc1, lc2, lc3, ...)
>> > >
>> > >   Cette fonction est appellee chaque fois que le client doit jouer
>> une
>> > >    carte.
>> > >   Le serveur fourni les cartes du tour precedent en parametre (lc3
>> varie en fonction du nombre de joueur), le client renvoit la
>> carte qu'il veut joueur.
>> > >   Tant que la carte n'est pas valide, le serveur demande au client
>> de rejouer une carte.
>> > >
>> > >
>> > >   * void card_valide (card)
>> > >
>> > >   Cette fonction est appellee si la carte card jouee par le client
>> (avec set_card) est valide.
>> > >   Elle permet au client de savoir que la carte card a ete acceptee
>> par le serveur.
>> >
>> > ici, quel doit etre l'algo a mettre en place si la carte est non
>> valide?
>> >
>> soit la carte est non valide et le serveur refait un appel set_card
>> pour que le client joue une carte valide.
>> soit la carte est valide et le serveur appel la fonction card_valide.
>>
>> un algo pourrai etre :
>>
>> card_is_valide = FALSE;
>> while (!card_is_valide)
>> {
>>   /* demande la carte au client */
>>   card_play = set_card ([parametres]);
>>
>>   card_is_valide = test_if_carte_is_valide (card_play);
>> }
>>
>> /* informe le client que sa carte est valide */
>> card_valide (card_play);
>>
>> et pendant le while, tant que le client cherche la carte qu'il va
>> jouer, les serveur fait un appel a other_set_card(place)  pour
>> informer les autres joueur que le client a la place place choisi une
>> carte.
>>
>> > >
>> > >
>> > >   * void other_set_card (place)
>> > >
>> > >   Cette fonction est appellee quand un autre joueur est en train
>> de choisir une carte a jouer. Le serveur fourni la place du
>> joueur qui est en train de joueur.
>> >
>> > et la carte, non?
>> >
>> quelle carte ? celle que l'autre client va jouer ? a priorie quand on
>> est dans cette fonction on ne sait pas quelle carte va joue le client
>> qui est en train de choisir sa carte.
>>
>> cette fonction est juste la pour dire que untel choisis une carte (et
>> que ca peut prendre du temps).
>>
>> > >
>> > >
>> > >   * void end_of_turn (c1, c2, c3, ..., lc1, lc2, lc3, ...)
>> > >
>> > >   Cette fonction est appellee a la fin d'un tour. le serveur
>> fourni les cartes jouees dans le tour (c1...) ainsi que les
>> cartes du tour precedent (lc1...).
>> > >   Les bornes c3 et lc3 dependent du nombre de joueur.
>> > >
>> > >
>> > >   * {announce} set_announce (a1, a2, a3, ...)
>> > >
>> > >   Cette fonction est appellee lorsque le serveur a besoin de
>> connaitre les annonces des clients (juste apres le 1er tour, il
>> me semble). Il fournit les annonces des autres joueurs et le
>> client renvoie son annonce (s'il veut en faire une).
>> > >
>> > >
>> > > Fin de partie :
>> > > -------------
>> > >
>> > >   * {replay} end_of_game (contract, win, score, oudlers,
>> > >                           sc1, sc2, sc3, ..., chien1, chien2,
>> chien3, ...)
>> > >
>> > >   Cette fonction est appellee en fin de partie si le jeu c'est
>> deroule normalement ou que tout le monde a passe.
>> > >
>> > >   Le serveur fourni :
>> > >     contract : le contrat du preneur
>> > >     win : TRUE si le preneur a gagne, FALSE autrement
>> > >     score : le score du preneur pour la partie
>> > >     oudlers : le nombre d'oudlers du preneur
>> > >     sc1, sc2, sc3 ... : les scores totaux de tous les joueurs
>> > >      (score de la partie ajoute aux scores precedents, pour chaque
>> joueur). sc3 peut varier en fonction du nombre de joueurs.
>> > >     chien1, chien2, chien3, ... : les cartes dans le chien.
>> > >     chien3 peut varier en fonction du nombre de joueurs.
>> > >
>> > >   Si tout le monde a passe, contract vaut BID_PASSE et les cartes
>> du chien sont affectees, les autres valeurs sont non definies.
>> > >
>> > >   Le client renvoi replay qui vaut TRUE si le client veut rejouer
>> ou FALSE dans le cas contraire.
>> > >
>> > >
>> > > Cas particulier :
>> > > ---------------
>> > >
>> > >   * void normal_close (void)
>> > >
>> > >   Cette fonction est appellee si la connexion a ete fermee
>> > >   normalement(en fin de partie quand quelqu'un a dis qu'il voulait
>> quitter le jeu)
>> > >
>> > >
>> > >   * void lost_connexion (void)
>> > >
>> > >   Cette fonction est appellee dans le cas ou il y a eu une
>> > >   deconnexion. Elle permet d'informer les clients que le jeu ne se
>> deroule plus normalement.
>> > >
>> > >
>> > >
>> > > Voila, pour l'instant ces fonctions sont faites dans libmt_client.
>> Et donc avec le protocole actuel c'est la libmt_client qui demande
>> au client de faire telle ou telle action (donc la libmt_client
>> implemente le meme protocole que le serveur).
>> > >
>> > > Avec le nouveau protocole, ce serai bien de faire en sorte que ce
>> soit le serveur qui demande au client de faire telle ou telle
>> action. La libmt_client n'etant la que pour etablir la connection,
>> gerer le reseau et informer le client de ce que le serveur lui
>> demande. Dans ce cas, seul le serveur serai au courant du
>> > > deroulement du jeu, les clients ne faisant que repondre a ce que
>> le serveur leur demande(ie: il n'y aurai plus qu'une seule
>> > > implementation du protocole : celle du serveur).
>> >
>> > Ceci n'etait pas le protocole mais un inventaire des procedures qui
>> sont ou seront dispo chez tout client qui se veut compatible avec
>> maitretarot.
>> >
>> > Il faut donc maintenant...
>> > 1/ definir le protocole.
>> > Pour une fonction A qui prend comme arguments arg1, arg2...argn et
>> qui renvoie r1, r2...rn, avec argi et ri de type int ou string, il
>> faut pouvoir encoder tout cela dans un format independant du nom de
>> la procedure, du nombre et du type des arguments et des valeurs de
>> retour.
>> >
>> Oui.
>> Est-ce qu'on peut utiliser que des strings, sachant que quand on doit
>> avoir un int, c'est au client (ou a la lib) de decoder.
>>
>> exemple: get_card (c1,c2, ....)
>>
>> avec ce qui circule sur le reseau : c1 = "10"
>> et le client decode la carte (sachant qu'il attend un int) en le
>> convertissant explicitement :
>>
>> carte_1 = string_to_int (c1);
>>
>> ceci evite le probleme d'architecture (big/little endian).
>> et evite d'avoir a faire un test sur le type du parametre.
>>
>> sinon, on peut realiser ca de la maniere suivante :
>>
>> [params_sortie] appel_fonction (string param1, string param2, ...) {
>>   /* definition de la commande */
>>   st = forme_la_chaine ("%s%s%...", nom_de_la_fonction_a_apeller,
>> param1, param2);
>>
>>   /* envoi de la commande */
>>   envoi_sur_le_reseau (st, taille (st));
>>
>>   /* lecture des valeurs renvoyees */
>>   param_sortie = lecture_sur_le_reseau ();
>>
>>   return param_sortie;
>> }
>>
>> la partie conversion int_to_string et string_to_int se fait en
>> dehors de cette fonction.
>> on peut presque faire la construction de la chaine a envoyer en
>> dehors de cette fonction.
>> => un fonction qui code la commande
>> => envoie de la commande (une chaine de caracteres)
>> => une fonction qui decode les parametres de sortie.
>>
>> la commande etant de la forme :
>>
>> "nom_fonction param1 param2 ..."
>> ou les param sont des strings.
>>
>>
>> > 2/ implementer le protocole
>> > Le serveur doit generer les commandes au format du protocole,
>> > recuperer les valeurs de retour et les interpreter
>> > Le client doit interpreter les commandes et appeler les fonctions
>> associees, puis encoder les valeurs de retour suivant le format du
>> protocole
>> >
>> ouep, voir juste au dessus.
>>
>> > 3/ faire de la verification d'erreur et implementer un
>> > sous-protocole de traitement d'erreur (que faire si le client ne
>> renvoie rien, ou renvoie des donnees insuffisantes, trop nombreuses
>> ou au mauvais format...?)
>> >
>> si le client renvoi des donnes fausses, on lui repose la question
>> jusqu'a ce qu'il reponde quelque chose de correct (et au bout de 10
>> fois on le deconnecte :)
>> >
>> >
>> > Quelques remarques...
>> >
>> > Nous abandonnons le format xml un moment envisage. C'est trop
>> > complexe a mettre en oeuvre par rapport au gain que ca apporte.
>> >
>> > Le protocole, a un niveau tres bas, disons couche 1, consistera a
>> envoyer des paquets. Un paquet est consitue de sa longueur (4
>> > octets) puis d'une chaine de caracteres representant le contenu du
>> paquet. Puis il faut definir comment on code les arguments string ou
>> int, ainsi que des constantes comme UNDEF. Et definir comment on
>> code une commande.
>> > La couche 2 consiste a utiliser ce codage pour envoyer des commandes
>> et des resultats
>> > La couche 3 coordonne tout cela, a savoir comment on fait pour
>> dialoguer.
>> >
>> >
>> > La couche 1 est deja codee.
>> > Ci-dessous, une proposition de codage des differents elements
>> > la couche 2 est encore d'ordre reseau puisqu'elle ne tient pas
>> compte du contenu de ce qui est envoye.
>> > la couche 3 est d'ordre applicative.
>> > Et evidemment, la couche 4 dont je n'ai pas parle, c'est les
>> > fonctions, qui sont propres a chaque client.
>> >
>> la couche 4 correspond a priorie a ce qu'il y a dans libmt_client, il
>> y a une couche de plus pour implementer les fonctions dans
>> chaques clients. Donc a part libmt_client, rien ne devrai changer dans
>> les clients deja codes.
>>
>> >
>> > proposition de codage des differents elements:
>> > - tout entier doit etre mis entre parentheses
>> > - toute chaine de caracteres doit etre mise entre guillemets.
>> > Comment coder un guillemet? On le double, on lui met un antislash
>> devant, ou on trouve autre chose?
>>
>> une methode pour coder les chaines de caractere est de reperer le " de
>> debut et le " de fin et de conciderer que tout ce qu'il y a a
>> l'interieur et qui est entre " est une chaine.
>>
>> exemple :
>>
>>   "la_fonction "param 1" "param 2 bla bla" "param_3""
>>   ^                                                 ^
>>   |                                                 |
>>   on repere ces 2 ", les autres " a l'interieur delimite des chaines
>> de caracteres.
>>
>> sinon (cf plus haut) je suis plutot partant pour mettre tous les
>> parametres sous forme de chaine de caractere et c'est au serveur ou au
>> client de savoir que tel parametre qu'il attent est un entier, et dans
>> ce cas il fait la conversion int_to_string.
>>
>> > - une valeur non definie sera 0. Remarque: 0 est donc different de
>> (0).
>>
>> ou une chaine vide : ""
>>
>> > - tout nom de procedure, vu qu'il est defini et fait partie de
>> l'ensemble des noms de procedures, n'a pas besoin d'un codage
>> > special. Simplement, pour les noms des procedures, nous
>> > n'utiliserons que des caracteres alphanumeriques (et le _).
>> >
>> > Jusqu'ici, on peut encore utiliser un parser fait avec du C.
>> > Pour la couche 2, si on va plus loin dans ce langage qu'on est en
>> train de definir, il faudra utiliser le parseur bison (yacc).
>> > Mais on peut aussi tenter quelque chose de simple. A voir...
>> >
>> je suis plutot pour quelque chose de plus simple, sachant que ce qu'on
>> veut faire n'a vraiment rien de complique (pas besoin de
>> sortir l'artillerie lourde :)
>>
>> > Bon, qui se devoue pour extraire les elements stables de cette
>> discussion et la mettre en format docbook dans un fichier sgml?
>> >
>> je transcrit les fonctions en sgml des qu'on ai d'accord sur
>> tout les termes :)
>>
>>
>> Philippe
>>
>> --
>> (    )
>>  ~oo~         Philippe Brochard    <address@hidden>
>>   .. Gnu!                           http://hocwp.free.fr
>>   / =\   \=
>>  -   -    -   -=-= http://www.fsf.org/home.fr.html =-=-
>>
>>
>> _______________________________________________
>> Maitretarot-devel-fr mailing list
>> address@hidden
>> http://mail.nongnu.org/mailman/listinfo/maitretarot-devel-fr
>> _____________________________________________________________________
>> GRAND JEU SMS : Pour gagner un NOKIA 7650, envoyez le mot IF au 61321
>> (prix d'un SMS + 0.35 euro). Un SMS vous dira si vous avez gagn_.
>> R_glement : http://www.ifrance.com/_reloc/sign.sms
>
>
> _______________________________________________
> Maitretarot-devel-fr mailing list
> address@hidden
> http://mail.nongnu.org/mailman/listinfo/maitretarot-devel-fr


-- 
- Homepage - http://ymettier.free.fr                   -
- GPG key  - http://ymettier.free.fr/gpg.txt           -
- MyAM     - http://www.freesoftware.fsf.org/myam      -
- GTKtalog - http://www.freesoftware.fsf.org/gtktalog  -







reply via email to

[Prev in Thread] Current Thread [Next in Thread]