Re: Communication a travers un socket unix

Top Page

Reply to this message
Author: ML Guilde
Date:  
To: guilde
Subject: Re: Communication a travers un socket unix
On Wednesday 22 October 2003 07:13, Philippe B. wrote:

> j'aimerais faire communiquer 2 programmes a travers un socket unix.
> Quelqu'un sait comment je pourrais m'y prendre ? le but est de faire
> communiquer une interface web avec des scripts bash ou du C.
>
> Qqun a une idée ? faut écrire ds un fichier ? comment créer le
> "socket" ?


Voici un petit exemple en C que j'ai dans un coin et que je ressore
regulierement pour montrer comment s'y prendre. Mais c'est fait pour 2
programmes ecrit par tes soins. Je n'ai pas tres bien compris dans ton cas
ce qui va communiquer. Peux-tu etre plus precis ? Il y a sans doute une
solution plus adaptee...

--
Frederic
/* A LIRE AVEC DES TABULATIONS DE 4
    --------------------------------    */



/* Cote Client : */

#include    <stdio.h>
#include    <stdlib.h>
#include    <errno.h>
#include    <signal.h>
#include    <string.h>
#include    <fcntl.h>
#include    <unistd.h>
#include    <sys/types.h>
#include     <sys/socket.h>
#include     <netinet/in.h>
#include     <netdb.h>



main()
{
    struct    sockaddr_in    ls_addr;
    struct    hostent      *host;
    int                    nbrEssais;
    int                    optSockVal;
    char                hostName[] = "serveur";        /*    Mettre le nom ou l'IP de la machine serveur    */
    int                    socketFlag = FALSE;
    int                    err;
    int                    s;
    int                    count,
                        nbOctets = 10;
    char                ptr[] = "Message pour le serveur";
    int                    sockPort = 2700;            /*    Ca peut etre une autre valeur    */


    if ((host = gethostbyname(hostName)) == NULL) {
        fprintf(stderr, "host 'serveur' inconnu\n");
        endhostent();
         exit(-1);
    }


    /*    On essaye de se connecter    */
    /*    Si le serveur ne repond pas, on attend 1s, puis on recommence    */
    /*    Au bout de 10 essais, on sort avec un message d'erreur    */        
    for (nbrEssais = 0; nbrEssais < 10; nbrEssais++) {
        s = socket(AF_INET, SOCK_STREAM, 0);
        if (s == -1) {
            fprintf(stderr, "Impossible de creer le socket\n");
         exit(-1);
        }
        ls_addr.sin_family = host->h_addrtype;
        ls_addr.sin_port = htons(sockPort);
        memcpy(&ls_addr.sin_addr.s_addr, host->h_addr, host->h_length);
        if (connect(s, (struct sockaddr *)&ls_addr, sizeof(ls_addr)) == 0) {
            socketFlag = TRUE;
            break;
        }
        else {
            printf("Essai %d (%d)\n", nbrEssais, errno);
            sleep(1);
            close(s);
        }
    }
    if (!socketFlag) {
        fprintf(stderr, "Impossible de se connecter au serveur\n);
        exit(-1);
    }


    /*    On modifie les options du socket pour qu'il garde la connexion    */
    optSockVal = 1;
    err = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optSockVal, sizeof(optSockVal));
    if (err == -1) {
        fprintf(stderr, "Erreur de modife des options du socket\n");
        exit(-1);
    }            


    /*    On envoit des donnees au serveur    */
    count = send(s, ptr, strlen(ptr), 0);


    /*    Puis on se met a l'ecoute du serveur. Appel bloquant    */        
    count = recv(s, ptr, nboctets, 0);


    if (count == nbOctets) {


        /*    Ok, lecture correcte    */
    }

    
    else if (count == 0) {
        /*    main : la connexion reseau est perdue    */
    }

    
    else if (count != 0) {
        /*    Nombre d'octets lus incorrect    */
    }

    
    close(s);

        
    exit(0):
}




/* Cote Serveur :

Attention, j'ai repique ca sous OS/9, en le modifiant de memoire pour Unix.
Il peut y avoir quelques petites fautes.    */


#include    <stdio.h>
#include    <stdlib.h>
#include    <errno.h>
#include    <signal.h>
#include    <string.h>
#include    <fcntl.h>
#include    <unistd.h>
#include    <sys/types.h>
#include     <sys/socket.h>
#include     <netinet/in.h>
#include     <netdb.h>


main()
{
    struct sockaddr_in    ls_addr, to;
    int                    err,
                        sx,
                        s,
                        count;
    char                ptr[80];
    int                    sockPort = 2700;            /*    Ca doit etre la meme valeur que le client    */

    
    /*    On cree un socket    */
    if ((sx = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        exit(err);
    }


    /* On autorise la reutilisation de l'adresse locale pour que bind */
    /* ne genere pas l'erreur 'Address Already in Use' (erreur constatée
    /* parfois) */
    if ((err = setsockopt(sx, SOL_SOCKET, SO_REUSEADDR, 0, 0)) == -1) {
        exit(err);
    }


    /*    On se 'bind' au socket    */
    ls_addr.sin_family = AF_INET;
    ls_addr.sin_port = htons(sockPort);
    ls_addr.sin_addr.s_addr = 0;

    
    if ((err = bind(sx, (struct sockaddr *)&ls_addr, sizeof(ls_addr))) == -1) {
        exit(err);
    }


    /*    On se met en attente d'une connexion sur le socket    */
    if ((err = listen(sx, <nbr maxi de connexions simultanees>)) == -1) {
        exit(err);
    }


    size = sizeof(struct sockaddr_in);


    while (1)
    {
        /*    On attend qu'une connexion soit demandee cote client */
        do {
            errno = 0;
            s = accept(sx, (struct sockaddr *)&to, &size);
        } while (errno == ECONNABORTED);


        if ((s == -1) && (errno != ECONNABORTED)) {
            exit(s);
        }


        if (s != -1)
        {
            /* A ce point, une connexion est etablie */
            /* Le socket s est une duplication du canal sx. */
            /* On utilise le socket s */

            
            /*    On attend une donnee du client */
            count = recv(s, ptr, <la meme taille que ce qui est emis>, 0);


            /*    puis on lui envoit quelque chose    */
            count = send(s, ptr, <la meme taille que ce qu'attend le client>, 0);
        }

        
        /* On attend une nouvelle connexion */
        close (s);    /*    On peut le laisser ouvert, ce qui permet de dialoguer avec plusieurs clients    */
                    /*    prevoir alors un tableau    */
    }
}