IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Vérifier si un programme est ouvert et l'utiliser


Sujet :

C

  1. #21
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    D'après mes lectures, ce serait à cause des administrateurs réseaux qui se mettraient trop vite à râler
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  2. #22
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    ben que ce soit un socjket standard ou un socket unix, ça va quand même créer un process..

    Donc si c'est à cause du nombre de process, c'est kifkif..

    Si c'est à cause du nombre de ports, sur unixoides on a quand même de la marge... Sur Windows oui c'est (très nettement) plus limité.


    Maintenant, pour ton problème de base, pourquoi ne pas utiliser des pipes ?
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  3. #23
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    pourquoi ?
    Parce que c'est mal !

    Plus précisément :

    • Sémantiquement, tu ne cherches pas à rendre l'application accessible depuis l'extérieur, mais simplement à signaler son existence. Et ça, on ne peut pas le savoir a priori ;
    • C'est une faille de sécurité potentielle. Si ton application n'est pas construite pour faire de la gestion réseau bien costaud, je peux éventuellement faire planter ton application et/ou ton système en ouvrant des milliers de connexions en parallèle, ou en lui envoyant des données corrompues ;
    • Cela oblige à accaparer un port réseau fixe et, en TCP ou UDP, ceux-ci sont limités. Avec seulement 65536 ports, les risques de collision ne sont pas négligeables ;
    • Cela oblige à rajouter une permission dédiée à ton firewall personnel s'il y en a un sur ta machine. Si c'est un administrateur système qui s'occupe de cela. Il est capable de te dire non pour le principe, et il aurait raison ;
    • Si tu optes pour le réseau, il faudra choisir le type de réseau que tu utilises. En grandes entreprises et sur de vieux serveurs, il est possible que ces machines n'utilisent pas TCP/IP mais en soient encore à IPX/SPX, par exemple (même si je reconnais que ça devient rare) ;


    Mais surtout :

    • Un port réseau dédié interdit de fait à ton application de fonctionner sur un serveur mutualisé (ce qui est quand même un des piliers des serveurs UNIX, et pas seulement eux).


    Là où je travaillais, nous utilisions plusieurs serveurs centralisés en salle machine (Solaris sur Sunfire, Linux IA32/64, et W2K idem) accédés par les utilisateurs avec des terminaux type thin client qui leur permettaient entre autres d'ouvrir plusieurs sessions en parallèle vers différents serveurs. Or, sur ce genre de plateforme, avec un port réseau dédié, le premier à lancer l'application la verrouille pour tous les autres utilisateurs, et reçoit indûment les requêtes de tous ces autres utilisateurs tentant de démarrer la même application.

    Le problème est exactement le même si tu ouvres plusieurs sessions utilisateurs sur un même PC de bureau.

    Là, pour le coup, l'admin aura une bonne raison de t'en vouloir, surtout si ton application a été écrite sur mesure (et donc coûté cher). Et si je suis si virulent, c'est parce qu'on a été confronté au problème.

    Citation Envoyé par souviron34 Voir le message
    Maintenant, pour ton problème de base, pourquoi ne pas utiliser des pipes ?
    Ça aurait l'avantage de fonctionner partout, y compris sur des UNIX extrêmement vieux ne proposant pas les sockets. Cela dit, si c'est pour voir si une application est déjà ouverte ou pas, on ne peut pas utiliser les pipes anonymes, et les tubes nommés ont les inconvénients rédhibitoires d'être à sens unique, d'une part, et de ne pas permettre de savoir s'il y a quelqu'un à l'autre bout (c'est le but). On reste en mode bloqué (sauf flag) qu'il y ait un processus qui refuse de lire, ou qu'il n'y ait pas de processus du tout.

  4. #24
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    • Un port réseau dédié interdit de fait à ton application de fonctionner sur un serveur mutualisé (ce qui est quand même un des piliers des serveurs UNIX, et pas seulement eux).

    ...
    Or, sur ce genre de plateforme, avec un port réseau dédié, le premier à lancer l'application la verrouille pour tous les autres utilisateurs, et reçoit indûment les requêtes de tous ces autres utilisateurs tentant de démarrer la même application.
    Euh.. je ne vois pas pourquoi.. Si le serveur est enregistré comme service, n'importe qui peut s'y connecter parallèllement...


    Citation Envoyé par Obsidian Voir le message
    Ça aurait l'avantage de fonctionner partout, y compris sur des UNIX extrêmement vieux ne proposant pas les sockets. Cela dit, si c'est pour voir si une application est déjà ouverte ou pas, on ne peut pas utiliser les pipes anonymes, et les tubes nommés ont les inconvénients rédhibitoires d'être à sens unique, d'une part, et de ne pas permettre de savoir s'il y a quelqu'un à l'autre bout (c'est le but). On reste en mode bloqué (sauf flag) qu'il y ait un processus qui refuse de lire, ou qu'il n'y ait pas de processus du tout.
    oui, mais d'après le message de troumad page précédente (en réponse au tien), il serait pas mal intéressé de pouvoir communiquer avec (lui passer des infos et autres), et pas seulement de savoir si il est ouvert...

    Il me semble que des pipes seraient le plus adapté, non ?
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  5. #25
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Ok, dans ce sens-là…

    C'est possible mais ça t'oblige à mettre en place un architecture explicitement client-serveur, et à gérer toutes les transactions avec les autres instances lancées légitimement. Ça complique beaucoup la chose pour rien, car ce n'était pas l'objectif initial (savoir simplement si une instance était déjà lancée). Ça pose aussi la question du propriétaire du processus serveur.

    Mais surtout, ça ne justifie toujours pas l'usage du réseau. Tout ceci peut toujours être fait en interne.

    C'est d'ailleurs toute la raison d'être des sockets : établir des points de communication entre processus. Mais les domaines dans lesquels ils peuvent être établis sont multiples, et si c'est en interne sur une machine UNIX, le plus indiqué reste toujours AF_UNIX.

    Il me semble que des pipes seraient le plus adapté, non ?
    À condition que ce soit le père qui lance le fils et qui lui fasse hériter des descripteurs, ce qui n'est pas l'objet du problème. On cherche toujours à savoir si, en lançant une application, celle-ci n'a pas déjà été lancée auparavant. Si c'est le cas, on peut éventuellement lui envoyer des ordres mais cela vient en second lieu.

    En fait, le problème de Troumad est celui du mutex, au sens large. On pourrait résoudre le problème avec d'autres choses, comme une IPC SysV, une fois mis d'accord sur le lieu de rendez-vous, mais ça pose toujours le problème du choix de l'ID, de la compatibilité entre plate-formes, de la possibilité de lancer plusieurs instances en parallèle, etc.

    Un truc à base de communications par sockets, donc identique à la programmation réseau, mais basé sur le système de fichiers (philosophie UNIX) et avec un espace de nommage bien plus vaste et bien plus explicite est clairement le plus indiqué.

  6. #26
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Un truc à base de communications par sockets, donc identique à la programmation réseau, mais basé sur le système de fichiers (philosophie UNIX) et avec un espace de nommage bien plus vaste et bien plus explicite est clairement le plus indiqué.
    en fait, un petit programme Fortran ou Pascal utilisant des common et block data ferait l'affaire

    ça doit d'ailleurs bien exister quelque part, la description de l'espace disque commun...

    A moins que ça ne soit ce que tu mentionnais plus haut ?

    Mais à priori on devrait pouvoir mettre directement tout un tas d'informations, pourvu qu'on ait la même définition de part et d'autre...



    (je n'ai jamais d'ailleurs compris pourquoi ce truc tellement utile n'avat pas été repris par les autres langages.. VMS avait à un moment donné (je ne le "fréquente" plus depuis belle lurette) utilisé un mécanisme similaire pour des variables système (un style de getenv/putenv, mais à travers l'ensemble du système, krnel compris))


    PS: à propos des sockets et clients/serveurs, je ne sais pas pourquoi cette notion de "service" a été plus ou moins oubliée...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #27
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    en fait, un petit programme Fortran ou Pascal utilisant des common et block data ferait l'affaire ; ça doit d'ailleurs bien exister quelque part, la description de l'espace disque commun... A moins que ça ne soit ce que tu mentionnais plus haut ?
    En effet.

    Je n'ai jamais eu à faire au Fortran (c'est une lacune :-) mais il me semble qu'un COMMON BLOCK se loge au sein d'un segment de mémoire partagée. Auquel cas le langage se rapproche du système pour créer ce segment puis le remplit, en lui ajoutant éventuellement un identifiant pour qu'on le retrouve.

    Donc, dans ce cas, cela va donner lieu à une IPC SysV dont je parlais plus haut.

    Mais à priori on devrait pouvoir mettre directement tout un tas d'informations, pourvu qu'on ait la même définition de part et d'autre...
    Là encore, le problème réside non pas dans l'échange de données (d'ailleurs facultatif pour le problème qui nous incombe aujourd'hui), mais dans le choix à l'avance du lieu de rendez-vous, identifiable sans ambiguïté. Accessoirement, ce serait sympa pour l'admin si cette ressource pouvait être humainement identifiable.

    (je n'ai jamais d'ailleurs compris pourquoi ce truc tellement utile n'avat pas été repris par les autres langages.. VMS avait à un moment donné (je ne le "fréquente" plus depuis belle lurette) utilisé un mécanisme similaire pour des variables système (un style de getenv/putenv, mais à travers l'ensemble du système, krnel compris))

    PS: à propos des sockets et clients/serveurs, je ne sais pas pourquoi cette notion de "service" a été plus ou moins oubliée...
    Elle n'a pas été oubliée. Elle passe son temps à être réinventée, à chaque fois sous des noms différents. En général, le cheminement est toujours le même. On crée une application, puis on se retrouve confronté au problème de gestion exclusive des ressources. Donc, on commence par mettre en place un système permettant à une instance de se signaler, puis on s'aperçoit que le problème s'étend au multi-utilisateurs, et là, on en arrive naturellement à créer son daemon pour gérer tout cela, et on se sent une âme d'architecte. :-) Ensuite, les daemons de ce style se multiplient. On se dit que ce serait bien d'avoir un truc unifié, mais cela implique à toutes les applications de respecter les règles d'un même framework.

    Et du coup, comme tout le monde réinvente plus ou moins la roue à un moment ou un autre, ça donne naissance à tout un tas de trucs comme CORBA, DCOM, ou DCOP puis D-BUS.

    On comprend ainsi que les architectures distribuées, même au sein d'une même machine, sont devenues une composante omniprésente de la programmation moderne. Mais pour qu'un de ces frameworks soit réellement plébiscité, il faudrait qu'il soit standardisé, que les normes des nouveaux systèmes d'exploitation spécifient sa disponibilité par défaut, et qu'il soit suffisamment bien conçu pour ne pas avoir à être revu de fond en comble après quelques années d'existence (c'est l'une des forces d'UNIX d'être encore exploitable avec des API âgées de 35 ans en moyenne).

  8. #28
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Visiblement mon problème pose problème !

    Après une longue lecture intéressante de vos propositions, j'aimerai voir rapidement les pipes...
    Citation Envoyé par Obsidian Voir le message
    Ça aurait l'avantage de fonctionner partout, y compris sur des UNIX extrêmement vieux ne proposant pas les sockets. Cela dit, si c'est pour voir si une application est déjà ouverte ou pas, on ne peut pas utiliser les pipes anonymes, et les tubes nommés ont les inconvénients rédhibitoires d'être à sens unique, d'une part, et de ne pas permettre de savoir s'il y a quelqu'un à l'autre bout (c'est le but). On reste en mode bloqué (sauf flag) qu'il y ait un processus qui refuse de lire, ou qu'il n'y ait pas de processus du tout.
    Je prévois de laisser un fichier avec l'id du processus (je m'en sers déjà sous LInux et Windows de cet id pour tester un peu). Après, je peux voir si le processus avec l'Id en question est bien le bon. Non ?
    Et finalement s'il existe je fais un pipe. La communication n'a pas besoin d'être bidirectionnelle. J'ai juste besoin de passer les argc et argv récupéré par le second programme appelé au premier qui tourne déjà.
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  9. #29
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par troumad Voir le message
    Je prévois de laisser un fichier avec l'id du processus (je m'en sers déjà sous LInux et Windows de cet id pour tester un peu). Après, je peux voir si le processus avec l'Id en question est bien le bon. Non ? Et finalement s'il existe je fais un pipe. La communication n'a pas besoin d'être bidirectionnelle. J'ai juste besoin de passer les argc et argv récupéré par le second programme appelé au premier qui tourne déjà.
    Un certain nombre de programmes procèdent déjà de cette manière.

    Mais en créant un socket UNIX, tu fais tout cela en une seule fois. Tu crées un socket avec l'appel socket(), lequel va prendre la forme d'un descripteur de fichier exactement comme le ferait pipe(). En guise d'adresse, tu choisis un nom de fichier, du style « /var/run/monapplication.monpid.sock », en rajoutant éventuellement un UUID si tu crains les collisions. Tu l'associes à ton socket avec bind() exactement comme tu le ferais avec une adresse IP. Cela va automatiquement créer l'entrée sur le système de fichier.

    À ce stade, n'importe qui peut voir si ton application est déjà lancée et avec quel PID. Avec un simple « ls », l'admin système peut déjà faire son travail si besoin.

    L'application étant identifiée, il suffit de se connecter à ce nom de fichier, là encore de la même façon que tu te connecterais à un port réseau pour voir si l'application répond, et si elle le fait correctement. Ça te permet de savoir d'un coup si

    — l'application existe toujours ;
    — si le processus qui occupe ledit PID est bien celui que l'on croit ;
    — si l'application n'a pas planté.

    Dans les autres cas, tu fais le ménage en supprimant l'entrée comme si c'était un fichier ordinaire (celui-là même que tu comptais créer). Donc avec « rm » depuis le Shell ou unlink() depuis le C.

  10. #30
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Je n'ai jamais eu à faire au Fortran (c'est une lacune :-) mais il me semble qu'un COMMON BLOCK se loge au sein d'un segment de mémoire partagée. Auquel cas le langage se rapproche du système pour créer ce segment puis le remplit, en lui ajoutant éventuellement un identifiant pour qu'on le retrouve.
    volà de quoi je parlais :

    Sharing Data

    ou

    Using Command Language Interpreter Symbols and Using the Common Area)

    Les variables internes du kernel de VMS sont également lisibles/settables par des symboles du même style (LIB$ ou les variables SYS$ (des exemples ici))


    Simplement génial...

    Et perdu pour beaucoup...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #31
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Mais en créant un socket UNIX,
    Cette méthode ne marchera pas sous Windows ? Si ?
    Mon programme doit marcher aussi sous Windows.
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  12. #32
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    J'ai trouvé une petite réponse à une petite question :
    Citation Envoyé par troumad Voir le message
    (peut-être que gtk gère ça ?)
    http://gtk.developpez.com/doc/en/gtk/GtkSocket.html
    Mais, vais-bien utiliser les socket si je veux la compatibilité WIndows-Linux ?
    À moins que la méthode conseillée sous Windows n'existe pas sous Linux ?
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  13. #33
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par troumad Voir le message
    Cette méthode ne marchera pas sous Windows ? Si ?
    Mon programme doit marcher aussi sous Windows.
    Non.

    Mais les processus sont une notion inhérente à système d'exploitation, au sens large. Les gérer relève donc de la programmation système. Il te faut donc écrire une fonction appelée par ton programme principal et qui, elle, choisira la meilleure méthode à suivre en fonction de l'environnement dans lequel elle se trouve.

    Même au sein d'un même O.S., d'ailleurs. Sous Linux, par exemple, en fonction du fichier de configuration, tu peux lui demander d'utiliser des sockets UNIX par défaut, ou d'utiliser D-Bus, si le fichier le précise et si elle peut en trouver (là encore) une instance active.

    Pour Windows, il y a beaucoup de choses disponibles : voir Interprocess Synchronization.

    Citation Envoyé par troumad Voir le message
    J'ai trouvé une petite réponse à une petite question :http://gtk.developpez.com/doc/en/gtk/GtkSocket.html
    Mais, vais-bien utiliser les socket si je veux la compatibilité WIndows-Linux ?
    À moins que la méthode conseillée sous Windows n'existe pas sous Linux ?
    L'idée d'utiliser les sockets correspond surtout à quelque chose que l'on peut considérer comme standard sur tous les UNIX aujourd'hui, et qui fait directement partie du système.

    Ici, tu utilises GTK, qui fait une bonne partie du travail à ta place, mais qu'il faut installer avec ton application ou vérifier sa disponibilité. Si tu t'appuies déjà sur cette lib, alors elle doit elle-même proposer directement d'autres facilités pour mettre des données en commun, en s'appuyant sur les facilités que chaque système propose.

    Je ne les ai plus en tête, mais tu peux faire une recherche…

  14. #34
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Je viens de me faire un client serveur avec vérification simple des données transmises.
    Voici le fichier qui marche ne mode client si le serveur est déjà lancé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
     
    #define SERVER_PATH     "/tmp/server"
    #define BUFFER_LENGTH    250
    #define FALSE              0
     
    #ifndef SUN_LEN
    #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path)) 
    #endif
     
    int main(int argc, char *argv[])
    {
       int    sd=-1, sd2=-1, rc;
       unsigned short i,c;
       char   buffer[BUFFER_LENGTH],buffer1[BUFFER_LENGTH];
       struct sockaddr_un serveraddr;
       char d;
       pid_t pid;
     
     
          sd = socket(AF_UNIX, SOCK_STREAM, 0); /* création du socket AF_UNIX : on ne passe pas par un port, ce sera interne au PC */
          if (sd < 0)      /* retour un entier si ça c'est bien passé, sinon -1 */
          {
             perror("echec de socket()");
          }
          else
          {
    	serveraddr.sun_family = AF_UNIX;
    	if (argc > 1)
    	  strcpy(serveraddr.sun_path, argv[1]);
    	else
    	  strcpy(serveraddr.sun_path, SERVER_PATH);
     
    	rc = connect(sd, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
    	if (rc < 0)
    	{
    	  perror("serveur absent : le programme devient serveur");
     
    	  do
    	  {  
    	    memset(&serveraddr, 0, sizeof(serveraddr));
    	    serveraddr.sun_family = AF_UNIX;
    	    strcpy(serveraddr.sun_path, SERVER_PATH);
     
    	    rc = bind(sd, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
    	    if (rc < 0)
    	    {
    	      perror("echec de bind()");
    	      break;
    	    }
    	    do
    	    {  
    	      rc = listen(sd, 10);
    	      if (rc< 0)
    	      {
    		perror("echec de listen()");
    		break;
    	      }
     
    	      printf("Pret pour la connexion du client.\n");
     
    		sd2 = accept(sd, NULL, NULL);
    		if (sd2 < 0)
    		{
    		  perror("echec du accept()");
    		  break;
    		}
     
    		pid = fork();
    		if (pid==0)
    		{ /* le fils prend la main : le père va attendre le prochain processus qui demande la main */
    		    do
    		      { /* boucle sur la connexion ouverte */
    		        printf("programme pid %d attend communication\n",getpid());
    			rc = recv(sd2, buffer, sizeof(buffer), 0);
    			if (rc < 0)
    			{
    			  perror("echec de recv()");
    			  break;
    			} 
    			if (rc == 0 )
    			{
    			  printf("Le client a fermé la connexion\n");
    			  break;
    			}
    			if (rc<BUFFER_LENGTH)
    			    buffer[rc]=0; /*finir la chaine de caractères par un 0 car il n'est pas mis en fin du message */
     
    			c=0;
    			for (i=0;i<strlen(buffer);i++) /* fabrication du code de vérification */
    			{
    			  c^=buffer[i];
    			}
    			printf("%d bites de données ont été reçus signature %hu : %s\n", rc,c,buffer);
    			sprintf(buffer,"%hu",c);
    			rc = send(sd2, buffer, strlen(buffer), 0);
    			if (rc < 0)
    			{
    			  perror("echec de send()");
    			  break;
    			}
    		      }
    		      while (1); /* pour recevoir plusieurs fois : tant que le client n'est pas fermé */
     
     
    		      if (sd2 != -1)
    		      {
    			  close(sd2);
    			  sd2=-1;
    		      }
    		      return 0; /* le fils se tue à la fin de la communication */
    		}
    	    } while (1); /* Fin de la communication avec un process : passage au suivant */
    	                 /* si on lance trois fois le programme, le premier sera serveur et commencera à discuter avec le second */
    			 /* le serveur communiquera avec le troisième que lorsque le second sera fermé */
    	  } while (0); /* seul intérêt : arriver pour les break */
    	  unlink(SERVER_PATH); /* supprimer le socket du disque dur */
     
    	}
            else
    	do /* le serveur est présent : le programme prend la version client */
    	{ /* boucle sur la connexion ouverte */
    	    fflush(stdin);
    	    fgets(buffer, BUFFER_LENGTH, stdin);
     
    	    rc = send(sd, buffer, strlen(buffer), 0);
    	    if (rc < 0)
    	    {
    	      perror("echec de send()");
    	      break;
    	    }
     
    	  c=0;
    	  for (i=0;i<strlen(buffer);i++)
    	  {
    	    c^=buffer[i];
    	  }            
    	      rc = recv(sd,buffer1,BUFFER_LENGTH, 0);
    	      if (rc == 0)
    	      {
    		  printf("Le serveur a fermé la connexion\n");
    		  break;
    	      }
    	      if (rc<BUFFER_LENGTH)
    	      buffer1[rc]=0; /*finir la chaine de caractères par un 0 */
    	      printf("%d : %s\n",rc,buffer1);
    	      sscanf(buffer1,"%hu",&i);
    	      if (c==i)
    		printf("Vérification OK\n");
    	      else
    		printf("Erreur dans le transfert ici %hu, là-bas : %hu\n",c,i);
    	    fflush(stdin);
    	    printf("Continuer ? (o/n) : ");
    	    do
    	    c=getchar();	  
    	    while (c!='o' && c!='n'); 
    	    do /* vider le buffer jusqu'au saut de ligne */
    	    {
    	    d=getchar();	  
    	    printf("%c",d);
    	    }
    	    while (d!='\n'); 
    	}
    	while(c=='o');
     
       }
       if (sd != -1)
          close(sd);
       if (sd2 != -1)
          close(sd2);
     
       return 0;
    }
    Ce programme peut avoir plusieurs clients lancés en même temps => ils seront traités simultanément par les fils !

    Je viens donc de tester aussi les processus père/fils : un gros problème , le pid change. Il va falloir que je ruse ou que je revois ce que j'avais pensé !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  15. #35
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Hello !

    Félicitations, ton programme fonctionne. Il manque toutefois #include <unistd.h> en tête de programme et SUN_LEN() n'est pas reconnu sur ma distrib' Linux (Fedora 13 avec GCC 4.4.5).

    Une fois ces deux détails mineurs corrigés chez moi, ton programme semble fonctionner comme tu l'entends.

  16. #36
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Je corrige le #include qui manque et je cherche pour SUN_LEN() .
    J'ai rajouté deux autres corrections et commentaires.

    Je proposerais bien ce code comme exemple dans les sources C ! Mais je continue à travailler dessus...
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  17. #37
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par troumad Voir le message
    Je corrige le #include qui manque et je cherche pour SUN_LEN() .
    J'ai rajouté deux autres corrections et commentaires.
    Honnêtement, je ne suis pas assez vieux ni barbu pour savoir d'où vient cette macro, mais il est de fait qu'elle pose les mêmes problèmes à plusieurs personnes.

    http://mail-index.netbsd.org/tech-ne...0/11/0008.html

    Étant donné que la norme C, elle, spécifie clairement comment fonctionne sizeof et, par définition, fonctionne partout, tu peux utiliser « sizeof serveraddr » (sans l' « & ») à la place, comme tout le monde.

    Je proposerais bien ce code comme exemple dans les sources C ! Mais je continue à travailler dessus...
    J'ai failli le faire également mais j'ai préféré te laisser aller au bout, et c'était apparemment une bonne chose. N'hésite pas à le faire quand tu auras fini.

  18. #38
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    J'ai trouvé ça pour le remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #ifndef SUN_LEN
    #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path)) 
    #endif
    Je trouve très bizarre le "((struct sockaddr_un *) 0)->sun_path)" ! Ce serait offsetof(struct sockaddr_un, sun_path) si je comprends.

    Par contre, dans ton exemple, il y a des choses que je ne comprends pas ! Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define STATIC_ASSERT(x) \
    do { \
      switch (1) { \
      case 0 != (x): break; \
      case 0: break; \
      } \
    } while (0)
    Ça fait quoi ?

    Le programme que tu proposes rajoute une sécurité au niveau du débordement de l'addition.
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  19. #39
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    À dire vrai, je ne « proposais » pas le programme joint. C'était la discussion sur SUN_LEN() qui m'intéressait.

    Citation Envoyé par troumad Voir le message
    J'ai trouvé ça pour le remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #ifndef SUN_LEN
    #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path)) 
    #endif
    Je trouve très bizarre le "((struct sockaddr_un *) 0)->sun_path)" ! Ce serait offsetof(struct sockaddr_un, sun_path) si je comprends.
    Oui. Mais offsetof() est elle-même censée être une macro définie par la norme C (je ne sais pas à partir de quand, par contre) et se trouvant dans stddef.h. Ceci permet d'éviter d'avoir à inclure ce fichier uniquement pour cette ligne.

    En plus, à cause de certaines ambiguïtés, stddef.h ne se trouve pas forcément à la racine de /usr/include (Sous GNU/Linux, on ne le trouve qu'en dessous de /usr/include/linux, comme si c'était une spécificité du noyau) et en plus, GCC code cette macro en dur :

    http://en.wikipedia.org/wiki/Offsetof
    http://gcc.gnu.org/onlinedocs/gcc-4..../Offsetof.html

    Par contre, dans ton exemple, il y a des choses que je ne comprends pas ! Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define STATIC_ASSERT(x) \
    do { \
      switch (1) { \
      case 0 != (x): break; \
      case 0: break; \
      } \
    } while (0)
    Ça fait quoi ?
    Ça ressemble à un hack assez obscur pour faire, comme son nom l'indique, un assert statique (même si assert() est une macro, elle teste la véracité de ton expression au runtime et appelle au final une fonction de la libC) en générant un code qui soit ne peut pas compiler si x est faux, soit génère un code toujours vrai et ne faisant rien, pouvant être optimisé et donc annihilé par le compilo. C'est donc un assert() au niveau de la précompilation.

  20. #40
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Donc, si x est faux, on aura deux "case 0", donc la compilation ne se fera pas. Pour ceci, il faut que x soit connu lors de la compilation. C'est bien ça ?
    Le x en question est "sizeof *addr == offsetof(struct sockaddr_un, sun_path) + sizeof addr->sun_path" dans le contexte suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    static socklen_t
    calc_sockaddr_un_size(const char *path)
    {
      struct sockaddr_un *addr;
      size_t size;
     
      if (strlen(path) < sizeof addr->sun_path) {
        return sizeof *addr;
      }
     
      /* Ensure that sun_path is the last member */
      STATIC_ASSERT(sizeof *addr ==
          offsetof(struct sockaddr_un, sun_path) + sizeof addr->sun_path);
    Je suis autodidacte en C : mes profs ne connaissaient que le Pascal
    Et là, il y a des choses qui me dépassent !
    1) pourquoi pas de () après le sizeof
    2) je ne comprends pas l'égalité qui doit être testée !
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

Discussions similaires

  1. Vérifier que le programme est ouvert
    Par Loenix dans le forum Programmation multimédia/Jeux
    Réponses: 2
    Dernier message: 14/05/2009, 15h50
  2. Vérifier si un programme est ouvert
    Par wonderboutin123 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 03/02/2008, 11h36
  3. Vérifier si calc windows est ouverte ou pas???
    Par electrosat03 dans le forum Contribuez
    Réponses: 4
    Dernier message: 10/03/2006, 19h28
  4. Vérifier qu'un formulaire est ouvert
    Par com800 dans le forum WinDev
    Réponses: 2
    Dernier message: 07/04/2005, 20h27
  5. Vérifier si une form est ouverte
    Par nivet dans le forum Langage
    Réponses: 6
    Dernier message: 23/11/2004, 09h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo