René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

FIFO / Named Pipes

Das grosse Problem von Pipes ist, dass zwei Prozesse, die nicht in einer Eltern Kind Beziehung stehen, nicht mitteinander kommunizieren können. FIFOs umgehen dies, indem statt Filedescriptoren Namen für die Endpunkte verwendet werden.

Unter Unix

Eine Named Pipe namens aPipe erstellen:
mknod aPipe p
mknod ist für System V4, BSD: /etc/mkfifo
Aus der Pipe lesen:
while true;
do
cat aPipe;
done
In die Pipe schreiben:
echo hallo du da > aPipe
echo wie geht es denn > aPipe

Unter NT

Dieses Beispiel demonstriert einen Ping Pong Chat. Ping Pong darum, weil derjenige, der das letzte Wort gesendet hat, blockiert ist, bis der andere wieder ein Wort gesendet hat. Dass nur ein Wort gesendet werden kann, ist eine weitere Beschränkung, um das Beispiel möglichst einfach zu halten.

Der Client

#include <windows.h>
#include <process.h>
#include <stdio.h>

#include <sstream>
#include <iostream>

using namespace std;

int main(int argc, char* argv[]) {
  if (argc != 2) {
    cout << "Client <name>";
    return 0;
  }

  stringstream nameOfPipe;
  nameOfPipe<< "\\\\.\pipe\\" << argv[1];

  HANDLE hPipe = 
    CreateFile(nameOfPipe.str().c_str(),
    GENERIC_WRITE | GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    (HANDLE)
    NULL);

  if(INVALID_HANDLE_VALUE == hPipe) {
    cout << "Konnte Pipe nicht ffnen" << endl;
    return 0;
  }

  DWORD nofRead,
        nofWritten;
  
  string ans;
  char bufIn [1000];

  while (1) {
    // Eingabe einlesen...
    // (Beschraenkung: nur ein Wort)
    cout << "?" << flush;
    cin >> ans;

    // .. und sie senden
    WriteFile(hPipe,ans.c_str(),ans.length(),&nofWritten,0);

    ReadFile(hPipe,
    bufIn, sizeof(bufIn), &nofRead, NULL);

    bufIn[nofRead]=0;
    cout << ">" << bufIn << endl;
  }

  return 0;
}

Der Server

#include <windows.h>
#include <process.h>
#include <stdio.h>

#include <sstream>
#include <iostream>

using namespace std;

int main(int argc, char* argv[]) {
  
  if (argc != 2) {
    cout << "Server <name>";
    return 0;
  }

  stringstream nameOfPipe;
  nameOfPipe << "\\\\.\pipe\\" << argv[1];

  char bufIn [1000];

  HANDLE hPipe = 
    CreateNamedPipe(nameOfPipe.str().c_str(),
    PIPE_ACCESS_DUPLEX,  // Beide Richtungen
    PIPE_TYPE_BYTE | PIPE_WAIT, 
    1, 0,0, // Hoechstens eine Verbindung, 
            // keine Buffer
    0,      // Timeout in Millisekunden
    NULL);  // Sicherheitsdesk

  if(INVALID_HANDLE_VALUE == hPipe) {
    cout << "Konnte Pipe nicht ffnen" << endl;
    return 0;
  }

  // Auf eine Verbindung warten
  ConnectNamedPipe(
    hPipe,
    0);

  DWORD nofRead,
        nofWritten;
  
  string ans;
  while (1) {
    ReadFile(
      hPipe,
      bufIn, sizeof(bufIn), &nofRead, NULL);

      bufIn[nofRead]=0;
      cout << ">" << bufIn << endl;

      // Eingabe einlesen....
      // (Beschraenkung: nur ein Wort)
      cout << "?" << flush;
      cin >> ans;

      // ...und senden
      WriteFile(hPipe,ans.c_str(),ans.length(),&nofWritten,0);
  }
  

  return 0;
}