pipes mit streams
-
Hallo,
es gibt schon viele Threads mit diesem Thema. Allerdings habe ich mir entweder eine so selten gesehen oder eine so dumme Problemstellung gestellt, dass ich dazu speziell noch nichts finden konnte.
Der Betreff sagt schon aus, dass ich mit c++ stream Mitteln über Pipes kommunizieren möchte.
Wäre auch eigentlich kein Problem, wenn ich mir über mkfifo() eine named pipe anlegen würde.
Allerdings bin ich während der Implementierung noch über die Funktion pipe() gestolopert, welche mir noch etwas eleganter vorkommt (da mkfifo() mir ja eine virtuelle Datei im FS anlegt).
So wie ich die Doku verstehe, erzeugt mir die pipe() Funktion eine Pipe und speichert mir im übergebenen Array die Filedeskriptoren (repräsentiert als Integer) für Ein- und Ausgabe.
Die Konstruktoren für ifstream/ofstream erlauben mir aber keinen Zugriff (soweit ich sehe) auf Filedeskriptoren, sondern nur auf Dateinamen, welche ich ja nur durch die Erstellung von virtuellen Dateien über z.B. mkfifo() bekomme.
Jetzt meine Frage:
Habe ich eine Möglichkeit mit C++ Bordmitteln auf diese erzeugten Filedeskriptoren zuzugreifen, oder muss ich mich den NamedPipes bedienen oder gibt es noch eine ganz andere alternative Möglichkeit?Falls ich wirklich über einige Threads gestolpert sein sollte, die genau diese Problemstellung behandeln, wäre ich über einen Hinweis darauf sehr dankbar!
Vielen Dank!
-
jghj schrieb:
Der Betreff sagt schon aus, dass ich mit c++ stream Mitteln über Pipes kommunizieren möchte.
Könntest du vielleicht noch angeben mittels welcher Bibliothek du pipes verwendest, oder unter welchem Betriebssystem? In der Regel gehören diese Fragen eher in die speziellen Unterforen (sowas wie WinAPI & Co).
-
mit C++ Stream Mitteln, wie du mich schon zitiert hast, meine ich die istream/ostream/ifstream/ofstream etc. derivate die in der standard c++ library mitgeliefert werden.
Deshalb hielt ich das C++ Forum auch für den richtigen Ausgangspunkt, auch wenn die angesprochenen Funktionen POSIX-lastig sind.
-
jghj schrieb:
mit C++ Stream Mitteln,...
...gibt es keine NamedPipes. Also bitte liefere doch nähere Informationen, damit dir vielleicht geholfen werden kann. Unix/Windows/Welche Bibliotheken...?
-
Linux.
Ich möchte keine NamedPipes verwenden. Mit dem angesprochenen mkfifo() Befehl würde eine Pseudo Datei, welche als NamedPipe verwendet wird erstellt, die ich dann mit den mir bekannten Konstruktoren von ifstream() bzw. ofstream() öffnen könnte.
Mit meinen anonymen Pipes bekomme ich aber nur Filedeskriptoren, wie man sie unter Anderem von Sockets (oder auch STDIN STDOUT STDERR => std::cin cout cerr) kennt.
Allerdings habe ich hier gerade etwas gefunden:
http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/filedescriptoroutbuffer.htmHier wird beschrieben, dass das was ich will nicht standardmäßig möglich ist, ich aber den beschriebenen Workaround wählen kann.
Vielen Dank für die Hilfe.
-
Naja, also "nicht möglich" ist irgendwie für mich nicht gleichzusetzen mit "einfach einen eigenen streambuf dafür definieren"
-
jghj schrieb:
Linux.
Ich möchte keine NamedPipes verwenden. Mit dem angesprochenen mkfifo() Befehl würde eine Pseudo Datei, welche als NamedPipe verwendet wird erstellt, die ich dann mit den mir bekannten Konstruktoren von ifstream() bzw. ofstream() öffnen könnte.
Mit meinen anonymen Pipes bekomme ich aber nur Filedeskriptoren, wie man sie unter Anderem von Sockets (oder auch STDIN STDOUT STDERR => std::cin cout cerr) kennt.
Allerdings habe ich hier gerade etwas gefunden:
http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/filedescriptoroutbuffer.htmHier wird beschrieben, dass das was ich will nicht standardmäßig möglich ist, ich aber den beschriebenen Workaround wählen kann.
Vielen Dank für die Hilfe.
Ich habe mal einen iostream auf einer pipe implementiert. Zu finden in meinen cxxtools als cxxtools::Pipestream. Die Klasse ist von std::iostream abgeleitet und verwendet ein cxxtools::Pipestreambuf als Streambuffer. Du kannst die Klasse so verwenden oder einfach schauen, wie ich das gemacht habe.
-
Du könntest Dir auch boost::iostreams anschauen.
Gruß
-
Drehleiter schrieb:
Du könntest Dir auch boost::iostreams anschauen.
Gruß
Nein!
-
Auf tntnets Seite scheinen die angegebenen Dateien nicht mehr vorzuliegen (ich krieg da jedenfalls nen 404)
jedenfalls hab ich mich grad selbst mit dem thema beschäftigt und folgenden Code fabriziert:
#ifndef __STREAMPIPE_H #define __STREAMPIPE_H #ifndef STREAMPIPE_BUFFERSIZE #define STREAMPIPE_BUFFERSIZE 4096 #endif #include <iostream> #include <pthread.h> using namespace std; class StreamPipe { friend void* DoPipe(void* StreamPipe); protected: pthread_t Thread; istream* in; ostream* out; public: void Start(istream& in, ostream& out); void Start(); void Stop(); void Wait(); StreamPipe(istream& in, ostream& out); ~StreamPipe(); }; void* DoPipe(void* Pipe) { istream* in = ((StreamPipe*)(Pipe))->in; ostream* out = ((StreamPipe*)(Pipe))->out; char Buffer[STREAMPIPE_BUFFERSIZE+1]; while(in->peek() != -1 && out->good()) { in->read(Buffer, STREAMPIPE_BUFFERSIZE); Buffer[in->gcount()] = '\0'; (*out) << Buffer; out->flush(); } return NULL; } StreamPipe::StreamPipe(istream& i, ostream& o) { Start(i,o); } StreamPipe::~StreamPipe() { Stop(); } void StreamPipe::Start(istream& i, ostream& o) { Stop(); in = &i; out = &o; Start(); } void StreamPipe::Start() { Stop(); pthread_create(&Thread, NULL, DoPipe, this); } void StreamPipe::Stop() { pthread_cancel(Thread); } void StreamPipe::Wait() { pthread_join(Thread,NULL); } #endif
Du erzeugst einfach ein StreamPipe Objekt und übergibst den istream und den ostream an den Konstruktor. Die Klasse erzeugt nen pthread, welcher den istream überwacht und alles, was da ankommt, an den ostream weitergibt... mit der Wait Methode kann man zB bei beendigung des Programms noch auf das ende des istreams warten und mit Stop kann man die Pipe anhalten...
damit kann man zB ein Programm schreiben, welches übergebene Dateien auf stdout ausgibt:
#include <fstream> #include "StreamPipe.h" using namespace std; int main(int argc, char** argv) { for(int i = 1; i < argc; i++) { ifstream in(argv[i]); StreamPipe Pipe(in,cout); Pipe.Wait(); } return 0; }
wegen den pthreads muss man beim kompilieren die -lpthread option angeben...
dadurch, dass die pipe in nem eigenen thread läuft, blockiert das Programm nicht bis der istream zu ende ist - dadurch kann man zB ne datei aus nem ifstream an einen socket stream (gibt's eigentlich iostreams für sockets? ich arbeite jedenfalls an welchen...) schicken ohne zu warten, bis sie komplett übertragen ist...