Raydium 3D Game Engine

Official forum for everything about Raydium, ManiaDrive, MeMak, ...
It is currently Thu Mar 28, 2024 5:25 pm

All times are UTC




Post new topic Reply to topic  [ 25 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Mar 13, 2006 8:23 am 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Bonjour (re) ...

Je suis en train de regarder la couche reseau de raydium.

Je voudrais pouvoir faire une recherche automatique de serveur.
Un client lancé (test6 par ex) soit se crée en serveur si il ne detecte aucun serveur dans le lan, soit s'accroche au serveur existant.

Pourrais-je avoir votre avis M. Xfennec ;o)
De quel coté chercher ?
Si j'utilise les primitive bas niveau de raydium pour broadcaster une adresse serveur, est ce que cela interferera avec la physique ?

A+
Jacques


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 13, 2006 9:29 am 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Premier point sur mon avis : l'idée est bonne. J'y ai pensé plusieurs fois sans jamais prendre le temps de me pencher plus sur la question.

Le problème ici n'est pas l'éventuelle interférence avec RayODE (la question était bonne, et après vérification, RayODE recherche bien uniquement ses propres paquets [avec un type RAYDIUM_NETWORK_PACKET_ODE_DATA]), mais la notion même de broadcast.
Pour l'heure, raydium_network_broadcast() est une fonction destinée à envoyer un paquet à chaque client connecté à la partie (utilisée par les serveurs, donc).

Il faudrait donc créer une nouvelle fonction de "broadcast IP" pour envoyer un paquet à tout le sous-réseau... et j'avoue que je vois ça comme quelque chose d'un peu compliqué (n'oublions pas l'aspect portable de Raydium). Je vais y penser dans mon coin :)

Tout ce travail (broadcast IP, recherche des serveurs, ...) doit bien sûr à terme être réalisé par Raydium, et non par chaque application.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 13, 2006 10:55 am 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
(après une [très] rapide recherche, il semble que cela ne soit pas si compliqué que ça. Les mots clefs pour les futures recherches sur ce sujet sont INADDR_BROADCAST et SO_BROADCAST)


Top
 Profile  
 
 Post subject: BroadCast de serveurs
PostPosted: Mon Mar 13, 2006 10:32 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Si ca peut aider, j'ai trouvé ces morceaux de codes ...
Voici les includes pour linux j'ai testé sous windows uniquement

Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>


Voici le code qui envoie le broadcast
Code:
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>


/*
    CpSc 824 -- SIMPLE datagram broadcast example...

    This program broadcasts a outMessageBuf to

         port 5824 (arbitrarily chosen)

    and waits for replies from whatever machines receive it...

*/

#define PORTNUMBER 5824

main (argc, argv)
int argc;
char *argv[];
{
    int socketDesc;    /* Socket Descriptor */
    int addrLength;
    struct sockaddr_in destinationAddr,
                       myAddr,
                       responseAddr;
    struct hostent *hostNameBufPtr;
    char outMessageBuf[128];
    char inMessageBuf[128];
    struct timeval timeOut;
    fd_set readReadySet;
    int msgCount;
    int trueFlag = 0x1;

    int ret;
    WSADATA WSAData;

    ret = WSAStartup(MAKEWORD(1,1), &WSAData);
    if (ret) { perror("network: FAILED ! (Winsock 2 Error: while asking for version 1.1)"); return(0); }

    /* Create socket from which to send */
    if ((socketDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("open error on socket");
        exit(1);
    }

    /* BIND the socket on our end to any available port (i.e.
       leave it up to the system to assign a port (used for
       replys */
    myAddr.sin_family = AF_INET;
    myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myAddr.sin_port = htons(0);    /* The zero says bind to any port */
    if (bind(socketDesc, (struct sockaddr *) &myAddr, sizeof(myAddr))
        < 0) {
        perror("bind error");
        exit(1);
    }

    /* And build BROADCAST address */
    destinationAddr.sin_family = AF_INET;
    destinationAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
    destinationAddr.sin_port = htons(PORTNUMBER);

    /* Set the socket to permit multicasts on the local LAN */
    if (setsockopt(socketDesc, SOL_SOCKET, SO_BROADCAST, &trueFlag,
                   sizeof(trueFlag)) != 0) {
        perror("setsockopt error");
        exit(1);
    }

    /* Broadcast message */
    strcpy(outMessageBuf, "Hello world");
    if (sendto(socketDesc, outMessageBuf, strlen(outMessageBuf)+1, 0,
        (struct sockaddr *)&destinationAddr, sizeof(destinationAddr)) < 0) {
        perror("socket send error");
        exit(1);
    }

    /* And wait for up to 5 seconds for replys to come back */
    /* Set timeOut value for receive to 5 seconds */
    timeOut.tv_sec = 5L;
    timeOut.tv_usec = 0L;

    /* Read responses from hosts accepting the multicast until a read
       finally times-out. */
    FD_ZERO(&readReadySet);
    FD_SET(socketDesc,&readReadySet);
    msgCount = 0;
    while (select(socketDesc+1,&readReadySet, NULL, NULL, &timeOut) > 0) {
        addrLength= sizeof(responseAddr);
        if (recvfrom(socketDesc,inMessageBuf,sizeof(inMessageBuf),0,
                     &responseAddr, &addrLength) < 0) {
            perror("socket read error");
            exit(1);
        }

        /* Convert the address of the responding machine to its symbolic
           format */
        if ((hostNameBufPtr=gethostbyaddr(&responseAddr.sin_addr.s_addr,
            sizeof(responseAddr.sin_addr.s_addr), AF_INET)) == NULL) {
            perror("gethostbyaddr error");
        }
        else {
            printf("Message received from %s\n", hostNameBufPtr->h_name);
        }
        printf("Received Message=%s\n\n",inMessageBuf);
        msgCount++;
        FD_SET(socketDesc,&readReadySet);
    }

    printf("Received %d messages\n",msgCount);

}


La partie WSAstartup est recupéré de raydium, a priori inutile pour linux

La partie reception:
Code:
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

/*
    In this example, the a "recvfrom" is used so a reply message may be
    returned to the node that sent the message.
*/

#define PORTNUMBER 5824

main () {
    int socketDesc;
    int senderAddrLength;
    struct sockaddr_in myAddr, senderAddr;
    char messageBuf[1024];
    struct hostent *senderNameBufPtr;
    char *senderPtr;
    int loopCnt;

    /* For testing purposes, make sure process will terminate eventually */
    //alarm(60);  /* Terminate in 60 seconds */

    int ret;
    WSADATA WSAData;

    ret = WSAStartup(MAKEWORD(1,1), &WSAData);
    if (ret) { perror("network: FAILED ! (Winsock 2 Error: while asking for version 1.1)"); return(0); }

    /* Create socket from which to read */
    if ((socketDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("open error on socket");
        exit(1);
    }

    /* Create "name" of socket */
    myAddr.sin_family = AF_INET;
    myAddr.sin_addr.s_addr = INADDR_ANY;
    myAddr.sin_port = htons(PORTNUMBER);

    if (bind(socketDesc, (struct sockaddr *) &myAddr, sizeof(myAddr)) < 0) {
        perror("bind error");
        exit(1);
    }

    /* Read from socket and then reply (note that the sender's address
       is placed in "senderAddr") */
    while (1) {
    for (loopCnt=0;loopCnt<5;loopCnt++) {
        senderAddrLength = sizeof(senderAddr);
        if (recvfrom(socketDesc,messageBuf,sizeof(messageBuf),0,
                     &senderAddr,&senderAddrLength) < 0) {
            perror("socket read error");
            exit(1);
        }

        /* Print out the name of the machine that sent the message */
        if ((senderNameBufPtr=gethostbyaddr(&senderAddr.sin_addr.s_addr,
              sizeof(senderAddr.sin_addr.s_addr), AF_INET))== NULL) {
           senderPtr= "(Unknown)";
        }
        else {
           senderPtr = senderNameBufPtr->h_name;
        }
        printf("Received message:%s from host %s\n",messageBuf, senderPtr);

        /* And return a response  to the sender */
        sprintf(messageBuf,"Got message %d",loopCnt);
        if (sendto(socketDesc, messageBuf, strlen(messageBuf)+1, 0,
            (struct sockaddr *)&senderAddr, senderAddrLength) < 0) {
            perror("socket send error");
            exit(1);
        }
    }
    }
}


Les tests sous windows, j'ai un souci.
En lanceant la partie reception sur deux machines XP sur un lan.
Si l'emetteur est lancée sur une des deux machines, tout ce passe bien.
Sur l'autre l'adresse n'est pas retrouvé (unknow) donc ca ne marche pas très bien, le serveur ne recoit pas la reponse du client.

Je ne sais pas pourquoi et je n'ai pas de debugger sur la deuxième machine.

A priori le fait que l'ip ne puisse pas etre resolue en nom ne devrait pas bloquer le retour de message.
Dans l'absolue ce n'est pas génant puisque le message passe.
Enfin la meme config machine permet de faire fonctionner test6 et tests en serveur.

Je pense que des lors on peut envoyer l'ip du serveur par broadcast toutes les seconde sur le port raydium+1

Deux autres questions:
Le serveur semble gourmant en resources, la charge du processeur est assez importante, meme lorsque le serveur tourne seul.

J'ai mis le sleep(0) dans le main. Il me semble qu'un serveur n'est pas aussi gourmand ?

Le ping (delay) reporté par le serveur me semble enorme ! 1840ms pour deux machine sur un lan. Le ping entre ces machines est <1ms.


Si cela peut aider ...

Pour info le codes viennent de la:
http://www.cs.clemson.edu/~wayne/cpsc824/


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 8:20 am 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Merci pour cette recherche.

A vrai dire, j'étais en train de poster un message hier soir pour expliquer que mes premieres expérimentations sous Linux étaient ok, et que je souhaitais pousser le test sous windows avant de me pencher sur le problème de l'intégration à la couche réseau de Raydium.

Sauf que la batterie du portable en a décidé autrement :)

Donc en bref, ça avance ... me restait à déterminer comment intégrer l'écoute des différents serveurs aux clients qui ne sont pas encore connectés (probablement en créant un 4éme mode : NONE, CLIENT, SERVER, et donc maintenant LISTEN), ce qui permettrait de continuer à n'utiliser qu'un seul port UDP. Il faut aussi déterminer les infos exportées par le serveur (nom, version, ?, ...)


Top
 Profile  
 
 Post subject: Resau
PostPosted: Tue Mar 14, 2006 8:26 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Bonjour,

Peux tu mettre le projet test6.c / tests.c a jour sur le svn et je ferais les tests windows d'ici la fin de la semaine.

A+
Jacques


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 8:42 pm 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Ouep. En fait, au vu de tes premiers résultats, j'ai directement commencé à intéger la recherche de serveurs à Raydium. Je ne sais pas trop combien de temps cela va prendre, mais j'espère arriver à quelque chose d'utilisable d'ici la fin de semaine pour qu'on puisse lancer les tests linux+win assez vite.

Enfin, ça c'est la théorie :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 8:46 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Tout cela va trop vite, ce n'est plus la peine que je regarde les broadcast de sockets ...
En fait je me rend compte que ca ira plus vite si je ne fais rien !
D'un autre coté je ramais pas mal.
Bon codage.
A+


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 10:33 pm 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Plus vite ? :) Ta recherche précédente me donne déjà une très bonne base pour la partie windows du problème. Cependant, il est clair que pour la partie intégration à Raydium, il est logique que ça aille vite pour quelqu'un qui a les "mains dedans" en permanence, et c'est bien ce point qui m'occupe en ce moment.

En revance, du point de vue des sockets, je rencontre un problème assez rude : sous Linux, sur une machine avec plusieurs interfaces réseau, les broadcasts ne partent que depuis la première carte ethernet (eth0) ... manque de chance, sur cqfd-corp.org, cette carte est reliée à internet, le réseau local étant sur eth1.

Je ne connais pas le comportement de windows sur des cas équivalent, mais j'imagine que la question se pose aussi (vu le nombre de jeux windows qui possèdent ce "bug") ...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 10:36 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
J'ai lu quelque part une option pour placer la socket en ecoute sur toutes les interfaces. Peut on faire de meme en emission ?

Je vais refaire une recherche au cas ou.

A+
Jacques


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 2:57 pm 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Linux semble avoir un comportement hérité de BSD sur ce point, ce qui laisse penser que windows n'a pas cette particularité et envoie bien le broadcast sur toutes les interfaces de la machine. Tu as moyen de faire le test ouille ?

Pour le cas Linux -> http://linuxfr.org/forums/19/15526.html


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 5:53 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Si tu as un prog tres simple je peux essayer.
Il va falloir que je trouve une machine avec plusieurs interfaces :(


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 10:22 pm 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Hop, ManiaDrive (svn commit 242) possède le nécessaire pour faire un premier test windows.

L'idée est la suivante :

- réussir à compiler la chose sous windows (absolument pas testé pour l'instant avec cette version de Raydium, probables problèmes !)
- lancer le serveur (mania_server.c)
- lancer le jeu (mania_drive.c)
- cliquer sur "LAN Multiplayer"
- La console (touche ² ou derrière le jeu si on le lance avec un --window) doit indiquer chaque seconde un truc du genre "***** debug - broad *****".

Si c'est le cas : c'est gagné !

Il faudrait faire (dans l'ordre) :
- le test entre 2 windows (ok entre 2 Linux pour l'instant)
- le tests entre 3 windows (1 serveur + 2 clients, chacun branché sur une carte réseau différente du serveur pour tester ce dont on parle dans les messages précédents. ok aussi pour Linux pour l'instant)
- mélanger tout ça à du linux ! :)

De mon coté, je me jette sur l'écriture de l'API cliente qui va permettre à l'utilisateur Raydium de lister les parties dispos et leurs infos.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 6:12 am 
Offline

Joined: Sun Mar 16, 2003 10:27 am
Posts: 404
Je n'ai pas le temps de tester pour l'instant mais voici ce qui ressort de la compilation sous windows des applis :

compilation mania2.C :
Code:
In file included from C:/RaydiumSDK/ray/raydium/network.c:10,
                 from C:/RaydiumSDK/ray/raydium/index.c:71,
                 from C:\RaydiumSDK\ray\mania2.c:9:
C:/RaydiumSDK/ray/raydium/headers/network.h:379: warning: type mismatch with previous implicit declaration
C:/RaydiumSDK/ray/raydium/callback.c:47: warning: previous implicit declaration of `raydium_network_read_faked'
C:/RaydiumSDK/ray/raydium/headers/network.h:379: warning: `raydium_network_read_faked' was previously implicitly declared to return `int'
In file included from C:/RaydiumSDK/ray/raydium/index.c:71,
                 from C:\RaydiumSDK\ray\mania2.c:9:
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_server_create':
C:/RaydiumSDK/ray/raydium/network.c:924: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_connect_to':
C:/RaydiumSDK/ray/raydium/network.c:979: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_discover':
C:/RaydiumSDK/ray/raydium/network.c:1053: warning: passing arg 4 of `setsockopt' from incompatible pointer type
success.


compilation mania_drive.c :
Code:
In file included from C:/RaydiumSDK/ray/raydium/network.c:10,
                 from C:/RaydiumSDK/ray/raydium/index.c:71,
                 from C:\RaydiumSDK\ray\mania_drive.c:14:
C:/RaydiumSDK/ray/raydium/headers/network.h:379: warning: type mismatch with previous implicit declaration
C:/RaydiumSDK/ray/raydium/callback.c:47: warning: previous implicit declaration of `raydium_network_read_faked'
C:/RaydiumSDK/ray/raydium/headers/network.h:379: warning: `raydium_network_read_faked' was previously implicitly declared to return `int'
In file included from C:/RaydiumSDK/ray/raydium/index.c:71,
                 from C:\RaydiumSDK\ray\mania_drive.c:14:
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_server_create':
C:/RaydiumSDK/ray/raydium/network.c:924: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_connect_to':
C:/RaydiumSDK/ray/raydium/network.c:979: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_discover':
C:/RaydiumSDK/ray/raydium/network.c:1053: warning: passing arg 4 of `setsockopt' from incompatible pointer type
success.


compilation mania_server.c :
Code:
In file included from C:/RaydiumSDK/ray/raydium/index.c:89,
                 from C:\RaydiumSDK\ray\mania_server.c:4:
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_server_create':
C:/RaydiumSDK/ray/raydium/network.c:924: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_connect_to':
C:/RaydiumSDK/ray/raydium/network.c:979: warning: passing arg 4 of `setsockopt' from incompatible pointer type
C:/RaydiumSDK/ray/raydium/network.c: In function `raydium_network_client_discover':
C:/RaydiumSDK/ray/raydium/network.c:1053: warning: passing arg 4 of `setsockopt' from incompatible pointer type
success.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 8:27 am 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
Ah ouais, quand même ... :)

Rien de grave à priori, je pense avoir tout corrigé avec le commit 243. Je vous laisse vérifier.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 25 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 31 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group