Definir qui est le serveur qui est le client ???

Résolu/Fermé
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 - Modifié par poparnassus le 6/02/2017 à 14:24
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 - 8 févr. 2017 à 14:12
Salut à tous et bonne année ca faisait quelque mois que je n'avais pas poster ici :----))) ,

Suite à mes poste précédent, je continu à développer une interface en C sous windows pour piloter un véhicule radiocommande, donc je souhaite utiliser le reseau wifi pour communiquer sur un raspberry, donc je dois utiliser les sockets !
Ma question, comment definir qui est le serveur qui est le client ?

Mon interface, les données générées par mon joystick sont stocker dans un tableau et doivent etre envoyer sur mon rasbperry, mais j'arrive pas à situer qui est le serveur/client car l'interface envoie les données sur le raspberry, le rasbperry transmet c'est données à la carte qui controle les moteurs, mais le rasbperry doit me retourner si les données ont été traiter par la carte de controle ou non., A tenir compte qu'il y a des capteurs sur la carte de controle, et sur le Raspb des contacteurs qui sont piloter via les gpio.

Ou alors es que je dois coder une appli serveur en C sur mon pc qui tourne en parrallele, et du coup mon interface et mon raspberry devienne tous les 2 des clients !!?? Ou je dis une connerie !

Je suis un peu perdu,
je vous remercie de vos future explication ^^

mon premier organnigrame ^^

3 réponses

[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
Modifié par [Dal] le 7/02/2017 à 14:05
Salut poparnassus,

Puisque c'est ton véhicule qui est à l'écoute des ordres envoyés à partir du PC, le serveur devrait être sur le Rapsberry et non sur le PC sur une architecture client - serveur.

Mais tu peux aussi faire du peer-to-peer, si le véhicule peut avoir besoin d'envoyer une information non sollicitée au PC (par exemple : mes batteries sont faibles, mon capteur IR ne fonctionne plus, etc.).

Tu peux faire tout cela en C de zéro avec les sockets.

Ou, si tu te limites à une architecture client - serveur, vu que tu as à ta disposition un Rapsberry, tu peux mettre dessus un serveur Web, et gérer l'exécution des ordres par des requêtes http GET (ou POST) envoyées au serveur, avec des scripts du côté serveur en Php, ou cgi Perl, Python, ou Bash, pour envoyer tes commandes sur les gpio.

Cela pourrait être plus facile qu'en C bien que plus consommateur en ressources.


Dal
0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
Modifié par poparnassus le 7/02/2017 à 16:06
je te remercie Dal une fois de plus,

[
le vehicule que je souhaite piloter [[[https://www.youtube.com/watch?v=cr_PngwdqhQ

j'ai installer ceci sur mon raspberry https://www.magdiblog.fr/gpio/berryio-une-interface-web-pour-controler-tous-les-ports-et-bus-du-raspberry-pi/ , donc cette appli passe par un serveur web qui tourne sur le rasp et me permet depuis mon navigateur du pc de controle mon raspberry, mais d'un point de vue performance pour ce que je souhaite faire je ne sais pas si c'est la meilleur soluce. et en plus de ca c'est pas fait pour piloter une carte arduino.

Les gpio:
Quand je suis connecter en ssh, si je veux activer une borne j'entre c'est commande là dans le shell
gpio -g mode 4 out //je passe la borne en mode sortie
gpio -g write 4 1 //1 pour borne acitve
gpio -g write 4 0 //0 pour borne desactiver


du coup c'est pour ca que je voulais utiliser les socket, pour pouvoir develloper totalement mes programmes, et aussi pour maitriser les socket.
Mes idees,
-un 1er script de" parametrage" qui boot au démarrage du raspberry aprés 1 min (pour etre sur que tout les périphérique du raspberry soit en ligne), qui me démarre les 2 scripts suivant.

- un 2eme qui se connecte a mon interface sur mon pc via les Socket. elle sera chargé de la commande des gpios
Par ex, Sur mon interface je crée un boutton sPOT LUMINEUX qui correspondra au GPIO 1, et quand je clique il transmet l'odre au rasp (ex une suite de chiffre qui sera traiter par le script) et hop le gpio 1 s'active.Ensuite le scipt me renvoie une confirmation de l'activation du gpio 1 (De cette maniere tant que la confirmation n'a pas été traiter par l'interface je bloque l'utilisation du boutton, et une fois la confirmation traiter, Si je re-clique il se desactive.

- un 3eme scipt qui transmet les données de contrôle moteur à la carte par les bornes I2C (I2C est une borne numérique qui sert à la communication entre le raspberry et la carte arduino, tandis que les gpio sont des bornes analogique)
Du coup se script relay juste les info de l'interface à la carte arduino.

- un 4eme qui sera destiné à la video qui aura pour but de transmettre les images du raspberry à l'interface


une question me vient à l"esprit, quand je dis script je parle de script python mais en faite c'est le language C ??? Actuellement j'apprends le C mais sous windows.

Du coup, si je dis pas de betise, je vais devoir utilisé 3 socket pour les scipt 2,3,4 ? Ou je peux utiliser une socket pour tous ca ?
Je me demandai même si je vais devoir utilisé les thread car je ne veux pas que mon interface se "fige" si le temps de reponse est trop long (a savoir d’après les test que j'ai fait, quand je lance la serie de commande gpio pour actvier gpio 1 par ex il se passe bien 1 à 2 seconde ...

Quand tu dis peer-to-peer c'est avec les soket ?


Autre point à tenir en compte (actuellement ce n'est pas une priorité):
je souhaite pouvoir programmer ou du moins injecter mes codes sur la carte de controle depuis mon interface en passant par le raspberry (je sais pas si c'est possible), en faite actuellement si je veux programmer cette carte je suis obliger de la connecter a mon pc en usb et d'utiliser le soft arduino.


J'ai l'impression que ca devient compliqué !!!! Merci en tous cas !
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
7 févr. 2017 à 16:47
non, c'est assez simple, et tu peux bazarder les sockets dans ton cas, sauf si tu veux te passer du serveur Web pour communiquer avec les gpio et le faire en C (avec un truc du genre http://www.airspayce.com/mikem/bcm2835/).

mais tu dis que tu as déjà installé un serveur web sur le Rapsberry et que :

Les gpio:
Quand je suis connecter en ssh, si je veux activer une borne j'entre c'est commande là dans le shell

gpio -g mode 4 out //je passe la borne en mode sortie
gpio -g write 4 1 //1 pour borne acitve
gpio -g write 4 0 //0 pour borne desactiver


Donc, si tu veux utiliser cet exécutable "gpio" de cette façon, tu peux paramétrer Apache pour gérer les scripts cgi, et exécuter un script en Bash (Perl, Python,... ou même C mais je ne vois pas l'intérêt du C ici puisque tu vas faire des appels système à la commande exécutable "gpio" en question), qui va envoyer ces commandes.

https://linuxconfig.org/simple-cgi-and-apache-examples-on-ubuntu-linux

Depuis ton programme sur le PC, tu peux utiliser le C pour envoyer des requêtes GET, par exemple, avec libcurl (vois cette procédure d'installation sous Windows : https://forums.commentcamarche.net/forum/affich-37594493-codeblocks-installer-une-bibliotheque-librairie, ou Perl, Python (ce sera plus facile dans ces langages),...

tes requêtes seront du genre :

GET http://ip.du.rapsberry/cgi-bin/manoeuvrer.sh?angleroues=0&vitesse=12

le script peut renvoyer éventuellement le résultat de l'exécution de la commande "gpio", si tu le captures et le renvoies sur la sortie standard, de façon à ce que le PC ait le résultat de l'exécution de la requête GET.

Choisis le langage de script cgi avec lequel tu es le plus à l'aise.

Quand tu dis peer-to-peer c'est avec les soket

en C oui

On pourrait aussi imaginer un autre moyen de communication si le véhicule doit communiquer une info sans être sollicité par le PC, mais le faire en C serait sans doutes plus efficace.


Dal
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
Modifié par [Dal] le 7/02/2017 à 17:03
l'avantage de le faire avec les sockets est que tu auras, normalement, moins de latence, que tu pourras utiliser UDP au lieu de TCP pour accélérer encore les temps de réaction,...

du côté des moins : c'est plus long à coder et plus laborieux :-)
0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
7 févr. 2017 à 18:37
ok je vais coder en C sur le raspberry étant donner que je commence à comprendre la programmation en C, j'ai réussi cette aprés midi a comprendre et faire marcher en local les socket avec client et serveur !! Quelque détaille a éclaircir mais ça va le faire !

Du coup, tu me conseilles de coder le serveur sur le raspberry ?
0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
Modifié par poparnassus le 7/02/2017 à 18:44
Par contre j'avais lue les differenncce entre udp et tcp et si j'ai bien compris je peux utiliser le protocole tcp pour le gpio car la j'ai besoin d'un "retour" avec le CRC
et UDP pour commander mon moteur puissque la je n'ai pas besoin de retour !
0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
Modifié par poparnassus le 8/02/2017 à 14:03
En faite c'est pas si simple les socket ^^

Serveur:
int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif

    /* Socket et contexte d'adressage du serveur */
    SOCKADDR_IN sin;
    SOCKET sock;
    char buffer[32];

    socklen_t recsize = sizeof(sin);

    /* Socket et contexte d'adressage du client */
    SOCKADDR_IN csin;
    SOCKET csock;
    socklen_t crecsize = sizeof(csin);

    int sock_err;
    int nombre_de_caractere;


    /* Si les sockets Windows fonctionnent */
    if(!erreur)
    {
        /* Création d'une socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);

        /* Si la socket est valide */
        if(sock != INVALID_SOCKET)
        {
            printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);

            /* Configuration */
            sin.sin_addr.s_addr = htonl(INADDR_ANY);  /* Adresse IP automatique */
            sin.sin_family = AF_INET;                 /* Protocole familial (IP) */
            sin.sin_port = htons(PORT);               /* Listage du port */

            sock_err = bind(sock, (SOCKADDR*)&sin, recsize);
            if(sock_err!=0)
            {
                printf("Impossible d'ecouter ce port: %d \n",sock_err);
            }
            else
            {
                printf("Bind OK\n");

            }

            sock_err=99;
            while(sock_err!=0)// Boucle tant qu'une demande de session (SYN) tcp n'a pas été reçu
            {
                sock_err = listen(sock, 5);
                printf("Listen OK PORT: %d \n", PORT);


                // Acceptation de la demande
                printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);
                csock=accept(sock, (SOCKADDR*)&csin, &crecsize);
                if(sock_err==SOCKET_ERROR)
                {
                    printf("\nDesole, je ne peux pas accepter la session TCP du a l'erreur : %d \n",WSAGetLastError());
                    return EXIT_FAILURE;
                }
                else
                {
                    printf("Un client se connecte avec la socket %d de %s:%d \n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));

                }

                //RECEPTION DONNEES
                nombre_de_caractere=recv(sock,buffer -1,32,0);
                if(nombre_de_caractere==SOCKET_ERROR)
                {
                    printf("Donnes non transmise \n");
                }
                else
                {
                    buffer[nombre_de_caractere]=0;
                    printf("Donnes client: \n %s",buffer);
                }

            }

            shutdown(csock, 2);
        }
        else
        {
            printf("erreur socket\n");
        }
             /* Fermeture de la socket client et de la socket serveur */
            printf("Fermeture de la socket client\n");
            closesocket(csock);
            printf("Fermeture de la socket serveur\n");
            closesocket(sock);
            printf("Fermeture du serveur terminee\n");
    }

    #ifdef WIN32
       WSACleanup();
    #endif

    return EXIT_SUCCESS;
}



Client:
int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif

    SOCKET sock;
    SOCKADDR_IN sin;
    char buffer[32] ;
    int nombre_de_caractere;

    //Init structure
    Input input;
    input.PRoueG = 0;
    input.PRoueD = 0;

    if(!erreur)
    {
         /* Création de la socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);

        /* Configuration de la connexion */
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);

        /* Si le client arrive à se connecter */
        if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
        {
            printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));

        }
        /* sinon, on affiche "Impossible de se connecter" */
        else
        {
            printf("Impossible de se connecter\n");
        }

        //ENVOI DONNEES
        strcpy(buffer,"Bonjour"); //copy la chaine dans buffer
        nombre_de_caractere=send(sock,buffer,strlen(buffer),0);
        if(nombre_de_caractere==SOCKET_ERROR)
        {
            printf("Impossible d'envoyer les donnees \n");
        }
        else
        {
            printf("Envoyer au serveur: %s\n",buffer);
        }
        system("pause");

        /* On ferme la socket précédemment ouverte */
        closesocket(sock);

        #if defined (WIN32)
            WSACleanup();
        #endif
    }
    return EXIT_SUCCESS;
}




RESULTAT SERVEUR
La socket 236 est maintenant ouverte en mode TCP/IP
Bind OK
Listen OK PORT: 23
Patientez pendant que le client se connecte sur le port 23...
Un client se connecte avec la socket 240 de 127.0.0.1:52603
Donnes non transmise
Fermeture de la socket client
Fermeture de la socket serveur
Fermeture du serveur terminee

Process returned 0 (0x0)   execution time : 3.965 s
Press any key to continue.

CLIENT
Connexion Ó 127.0.0.1 sur le port 23
Envoyer au serveur: Bonjour
Appuyez sur une touche pour continuer...


Je comprends pas pourquoi le serveur ne m'affiche le buffer = Bonjour
et en plus je souhaite que le serveur boucle meme si il nya pas de client
0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
Modifié par poparnassus le 8/02/2017 à 14:12
je viens de trouver mon erreur sur la socket
ligne 85 SERVEUR
nombre_de_caractere=recv(sock,buffer -1,32,0);
qui devient
nombre_de_caractere=recv(csock,buffer,32,0);
par contre j'arrive pas a faire boucler le serveur, une boucle pour si un le client se deconnecte, le serveur boucle en attente de co, et une autre boucle pour continuer la reception tant qun client est connecter !

Je continue mes recherche !
0