[C++] Interprozesskommunikation: Windows Pipes

04/01/2010 19:51 xNopex#1
Abend liebe Community,

Ich habe hier ein sehr interessantes Thema für euch: Kommunikation zwischen zwei Prozessen auf dem selben Computer. Das heißt, wie können zwei Programme, die auf einem System laufen, Daten untereinander austauschen? Dazu gibt es erstmal mehrere Möglichkeiten und ich habe mir da jetzt mal die Pipes rausgepickt. Die Frage, was ein Pipe ist, lasse ich mal durch Wikipedia klären. Dazu bitte HIER mal nachschauen. Um für euch den Umgang mit den Pipes einfach zu gestalten habe ich euch mal schnell zwei Klassen programmiert. Eine PipeServer- und einer PipeClient-Klasse. Damit ist es letztendlich nicht sehr schwer das Ganze zu realisieren :)

Ladet euch die Header- und .CPP-Dateien runter und bindet sie in euer aktuelles Projekt ein.
So, nun können wir anfangen zu Programmieren. Zuerst wollen wir einen Pipe-Server programmieren:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    return 0;
}
Der Code dürfte bisher eig. klar sein. Wir binden zuerst den iostream-Header für in- und output ein und dann den Header von unseren Pipe-Klassen. Unsere Klassen stehen zudem im Namensraum pipe, weswegen wir dem Compiler mitteilen, dass wir diesen im gesamten Projekt verwenden wollen. Dann erstellen wir mal ein Objekt der Klasse PipeServer:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeServer pipeServer;
    return 0;
}
Einfach :) Nun teilen wir der Klasse den "Namen" unseres Servers mit, anhand dem wir ihn später identifizieren können und die Größe des Servers in Bytes:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeServer pipeServer;
    pipeServer.SetPipeAttributes( "TEST", 512 );
    return 0;
}
In unserem Beispiel ist der Name also "TEST" und die max. Größe 512 BYTES. Nun können wir den Server erstellen und uns mit ihm Verbinden:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeServer pipeServer;
    pipeServer.SetPipeAttributes( "TEST", 512 );
    if( ! pipeServer.CreateServer() )
    {
        cout << "Konnte Server nicht erstellen\n";
        return 1;
    }
    if( ! pipeServer.ConnectToServer() )
    {
        cout << "Konnte sich nicht mit dem Server verbinden\n";
        return 1;
    }
    return 0;
}
Der Quellcode sollte wirklich nicht all zu schwer nachzuvollziehen sein ;) ConnectToServer ist nebenbei ein BlockingCall, das heißt der Programmablauf bleibt solange unterbrochen, bis sich ein Client noch mit dem Server verbunden hat. So nachdem sich ein Client mit dem Server verbunden hat, wird der Client an den Server ein Request senden. Diesen soll unser Server natürlich auch empfangen. Das geschieht mit der Funktion Recv(), die als Rückgabewert den empfangenen string enthält:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeServer pipeServer;
    pipeServer.SetPipeAttributes( "TEST", 512 );
    if( ! pipeServer.CreateServer() )
    {
        cout << "Konnte Server nicht erstellen\n";
        return 1;
    }
    if( ! pipeServer.ConnectToServer() )
    {
        cout << "Konnte sich nicht mit dem Server verbinden\n";
        return 1;
    }

    string empfangen = pipeServer.Recv();
    cout << "Empfangen: " << empfangen << "\n";
    return 0;
}
Natürlich wollen wir dem Clienten nun auch was zurückschreiben. Das geschieht mit der Funktion Send( string* ). Diese erwartet als Parameter einen Zeiger auf den String, der gesendet werden soll:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeServer pipeServer;
    pipeServer.SetPipeAttributes( "TEST", 512 );
    if( ! pipeServer.CreateServer() )
    {
        cout << "Konnte Server nicht erstellen\n";
        return 1;
    }
    if( ! pipeServer.ConnectToServer() )
    {
        cout << "Konnte sich nicht mit dem Server verbinden\n";
        return 1;
    }

    string empfangen = pipeServer.Recv();
    cout << "Empfangen: " << empfangen << "\n";

    string sende = "Huhu";
    pipeServer.Send( &sende );

    return 0;
}
Joa damit sind wir schon fertig mit dem Server. Ich sag ja, ist relativ einfach :) Nun bereitet uns der Client auch keine großen Probleme mehr denk ich. Wir erstellen wieder zuerst ein Objekt der Klasse PipeClient, übergeben dann die Daten vom Server (Name, Größe), verbinden ns mit dem Server, richten eine request an den Server und empfangen schließlich dessen Antwort:

Code:
#include <iostream>
#include <string>
#include "class_Pipe.h"

using namespace std;
using namespace pipe;


int main( int argc, char** argv )
{
    PipeClient pipeClient;
    pipeClient.SetPipeAttributes( "TEST", 512 );
    if( ! pipeClient.ConnectToServer() )
    {
        cout << "Konnte sich nicht mit dem Server verbinden\n";
        return 1;
    }
    string sende = "Hallo, Server";
    pipeClient.Send( &sende );
    string rec = pipeClient.Recv();
    cout << rec;

    return 0;
}
Wenn ihr Fragen habt, fragt, freue mich auch auf Feedback und wie immer Viel Spaß damit :D
03/21/2011 20:40 ftoby#2
Hey, die Dateien sind leider nicht mehr vorhanden, könntest du sie bitte noch einmal uppen?

Vielen Dank!
12/16/2011 23:44 Sharky85#3
Hallo xNopex,

ich bin an dein Header und CPP-Datein interessiert. Könntest du die eventuell nochmal hochladen?

Vielen Dank!

Gruß
Sharky
04/10/2012 14:15 l2iX#4
die Header- und .CPP-Dateien sind nicht mehr verfügbar :( könntest du die vllt noch mal hochladen?
04/10/2012 14:33 xNopex#5
Nä. Hab das selbst gelöscht. War wohl buggy und was weiß ich noch alles.