Anzeige:
Ergebnis 1 bis 6 von 6

Thema: IPC: Named pipes wieder zumachen und anderes

  1. #1
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719

    IPC: Named pipes wieder zumachen und anderes

    Ich arbeite gerade an einem OggVorbisPlayer, dem ich jetzt auch ein KonsolenInterface verpassen möchte,
    etwa das ich in der Konsole schreiben kann:

    "player -stop" und die Wiedergabe wird gestoppt, ohne das eine weitere Instanz des Players gestartet wird.

    Dazu hab ich bei Pronix.de die Möglichkeit gefunden, named pipes zu verwenden. Die Funktion

    Code:
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int mkfifo(const char *pfadname, mode_t mode);
    soll eine Pipe aufmachen. Jetzt hab ich mir gedacht, bevor das Programm etwas in die Pipe schreibt,
    muß es erstmal wissen, ob auch jemand aus der Pipe liest. Ich wollte das so machen, das ich die
    Pipe beim Start des Programmes erstelle und hinterher wieder zumache. Ein neuer Prozess muß
    dann nur gucken, ob es die Pipe gibt. Dazu brauch ich aber noch zwei Funktionen:

    - Herausfinden, ob die Pipe existiert
    - Pipe wieder zumachen

    Beides steht nicht dabei. Vielleicht könnt ihr helfen, und auch mal sagen, ob das ein gutes Verfahren ist,
    was ich mir da ausgedacht habe, oder ob ich es lieber anders machen sollte

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Vielleicht geht das mit einem Unix Domain Socket leichter.

    Ich muß zugeben, dass ich mich damit noch nicht so beschäftigt habe, aber ich habe das so verstanden, dass es fast wie ein Inertnetsocket ist, nur dass die Adresse praktisch ein Filename ist.

    Du hättest also eine Art Playerdaemon, der den Socket erzeugt und dann dort lesend wartet.

    Wenn der PLayerclient nicht dorthin connecten kann, muß er einen daemon starten.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719
    Ja, so in etwa hab ich mir das gedacht, nur das der Daemon eine GUI hat. Kannst du mal etwas Code oder einen Link zu Unix-Domain-Sockets posten? Damit hab ich mich nämlich noch nicht beschäftigt. Vielleicht könnte ich auch was mit DCOP basteln, ich weis nur nicht, ob das geht, da ich kein QT verwende

  4. #4
    Registrierter Benutzer
    Registriert seit
    04.07.1999
    Ort
    Zürich
    Beiträge
    221
    Hier ein kleiner Unix-Domain-Server und ein dazugehöriger Client. Sollte für den Anfang hilfreich sein. :-)

    uclient.c
    Code:
    /***
     * uclient.c - Einfacher Client für Unix-Domain-Sockets
     *
     * Verbindet sich mit dem ./sample-socket Unix Domain Socket,
     * kopiert stdin in den Socket und beendet sich dann.
     ***/
    
    #include <sys/socket.h>		/* connect(), bind(), listen(), accept() */
    #include <sys/un.h>		/* sockaddr_un */
    #include <unistd.h>		/* unlink() */
    #include "sockutil.h"
    
    int main(void)
    {
      struct sockaddr_un address;
      int sock;
      size_t addrLength;
    
      if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");
    
      address.sun_family = AF_UNIX;
      strcpy(address.sun_path, "./sample-socket");
    
      /***
       * Länge der Adresse inklusive Grösse des sun_family Elements
       ***/
      addrLength = sizeof(address.sun_family) + strlen(address.sun_path);
    
      if(connect(sock, (struct sockaddr *) &address, addrLength))
        die("connect");
    
      copyData(0, sock);
    
      close(sock);
    
      return 0;
    }

    userver.c
    Code:
    /***
     * userver.c - Einfacher Server für Unix-Domain-Sockets 
     *
     * Wartet auf eine Verbindung am ./sample-socket Unix Domain Socket.
     * Ist die Verbindung hergestellt, werden alle Daten von diesem Socket
     * nach stdout kopiert, bis die Verbindung vom anderen Ende geschlossen
     * wird, dann warten auf neue Verbindung.
     ***/
    
    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include "sockutil.h"
    
    int main(void)
    {
      struct sockaddr_un address;
      int sock, conn;
      size_t addrLength;
    
      if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        die("socket");
    
      /***
       * Berets vorhandene(n) Socket/Datei entfernen
       ***/
      unlink("./sample-socket");
    
      address.sun_family = AF_UNIX;
      strcpy(address.sun_path, "./sample-socket");
    
      /***
       * Länge der Adresse inklusive Grösse des sun_family-Elements
       ***/
      addrLength = sizeof(address.sun_family) + strlen(address.sun_path);
    
      if(bind(sock, (struct sockaddr *) &address, addrLength))
        die("bind");
    
      if(listen(sock, 5))
        die("listen");
    
      while((conn = accept(sock, (struct sockaddr *) &address, &addrLength)) >= 0){
        printf("---- Hole Daten ----\n");
        copyData(conn, 1);
        printf("---- Fertig ----\n");
        close(conn);
      }
    
      if(conn < 0)
        die("accept");
    
      close(sock);
      return 0;
    }

    Unix-Domain-Sockets haben eine einzigartige Fähigkeit: Mit ihnen können Dateideskripotren übergeben werden. Ein Prozess kann dadurch eine Datei öffnen und deren Dateideskriptor an einen anderen - möglicherweise völlig beliebigen -Prozess weitergeben. Die Zugriffsrechte werden nur beim Öffnen der Datei berücksichtigt, so dass der den Dateideskriptor erhaltende Prozess die gleichen Rechte auf die Datei erhält wie der Ursprungsprozess.
    Für die Übergabe von Dateideskriptoren sind die Funktionen
    Code:
    #include <sys/socket.h>
    int sendmsg(int fd, const struct msghdr * msg, unsigned int flags);
    int recvmsg(int fd, const struct msghdr * msg, unsigned int flags);
    zuständig.
    Doctrína est fructus dulcis radícis amárae.

  5. #5
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Original geschrieben von axeljaeger
    Ja, so in etwa hab ich mir das gedacht, nur das der Daemon eine GUI hat.
    Nunja, da wäre es eventuell dann sinnvoller, den Daemon ohne GUI zu machen.


    Kannst du mal etwas Code oder einen Link zu Unix-Domain-Sockets posten?
    Vielen Dank an f0rtex für diesen ausführlichen Beispielcode.
    Ich hätte sicher keinen so guten gefunden.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  6. #6
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719
    Ja, gut, Daemon macht man normal ohne GUI, aber es macht doch keinen Sinn, die PlayerUI zustarten und dazu noch einen Daemon, der drauf wartet, Nachrichten entgegen zu nehmen. Außerdem muß die GUI ja dann wieder benachrichtigt werden.

    Das mit dem Netzwerksocket scheint ja noch den Vorteil zu haben, das der Socket automatisch wieder zugemacht wird, wenn der Server beendet wird, auch wenn er unsachgemäß beendet wird. (Kann schon mal passieren bei meinen Player, nutzt intensiv NV-OpenGL)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •