Named Pipes Daten lesen und schreiben. Ihr seid meine letzte Hoffung, Huäää!
-
Hallo,
ich beschreibe mal mein Problem. Ich möchte einen Server initieren, der Daten sendet und einen oder mehere Clients, die Daten vom Server emfangen. Das ganze soll in einem MS Officeprodukt laufen. Da ich den Server zuerst in VBA entwicklet habe (nach Kodebeispielen von Microsoft), die aber nicht liefen, wei lder Server mehere
Threads erzeugen soll, weil ConnectNamedPipe, ReadFile, WriteFile, FlushFilePuffers
in eine "Loop" gehen. Im Thread ist das egal, da der parallel zum Program läuft.
Nachdem ich dann eine DLL erzeugt habe, werden die Threads angelegt und Daten in die Pipe geschrieben ohne das das Officeprodukt abstürzt.Meine Probleme:
Wenn ich Daten in die Pipe schreibe (vom Server...) erzeuge ich ja dann dort die Pipe. Gibt es eine Möglichkeit die Daten, die geschrieben werden sollen zu Beeinflussen, oder geht das nur so, das ich die Daten in einem String speicher, dann die Threads erzeuge. Die erzeugen die Pipes und warten auf Connect von den Clients. Dann an die Clients Daten broadcasten und die Pipes schließen und die Threads beim nächsten Sendewunsch dann wieder neu erzeugen,.....
Bislang loopt meine Routine und echoed die Daten vom Client.....
aber wirklich viel beim Client kommt auch nicht an..
Also schaut mal in den Code der DLL...#include "windows.h" #define DLL32Export __declspec ( dllexport ) #define MAXPIPES 20 DLL32Export int WINAPI CreateNamedPipes(char *szPipeName); DWORD WINAPI PipeInstanceThreadFunc( LPVOID lpParameter ); BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: { break; } case DLL_PROCESS_DETACH: { break; } case DLL_THREAD_ATTACH: { break; } case DLL_THREAD_DETACH: { break; } } return TRUE; } DLL32Export int WINAPI CreateNamedPipes(char *szPipeName) { int i; HANDLE hThread; DWORD ThreadID; for (i=0; i < MAXPIPES; i++) { if ((hThread = CreateThread( NULL, 0, PipeInstanceThreadFunc, NULL, 0, &ThreadID))==NULL) { MessageBox (NULL, "Thread creation failed", "Message", MB_OK | MB_ICONEXCLAMATION); return 0; } CloseHandle( hThread ); } return 0; } DWORD WINAPI PipeInstanceThreadFunc( LPVOID lpParameter ) { SECURITY_ATTRIBUTES Sec_Attrs; HANDLE hPipe; CHAR PipeBuffer[1024]; CHAR PipeBufferEx[5] = "Server"; DWORD BytesToRead; DWORD BytesWritten; Sec_Attrs.nLength = sizeof( SECURITY_ATTRIBUTES ); Sec_Attrs.lpSecurityDescriptor = NULL; Sec_Attrs.bInheritHandle = TRUE; if (( hPipe = CreateNamedPipe( "\\\\.\\PIPE\\AB23DF29CCAA27DFQW1", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, MAXPIPES, 0, 0, 2000, &Sec_Attrs)) == INVALID_HANDLE_VALUE ) { MessageBox (NULL, "Pipe creation failed", "Message", MB_OK | MB_ICONEXCLAMATION); return 0; } while (1) { if ( ConnectNamedPipe( hPipe, NULL )==0) { MessageBox (NULL, "Connect to pipe failed", "Message", MB_OK | MB_ICONEXCLAMATION); break; } while ( ReadFile( hPipe, PipeBuffer, sizeof( PipeBuffer ), &BytesToRead, NULL) > 0 ) { /* if (WriteFile (hPipe, PipeBuffer, BytesToRead, &BytesWritten, NULL) == 0) { MessageBox (NULL, "Pipe write failed", "Message", MB_OK | MB_ICONEXCLAMATION); break; } */ } if (WriteFile (hPipe, PipeBufferEx, 6, &BytesWritten, NULL) == 0) { MessageBox (NULL, "Pipe write failed", "Message", MB_OK | MB_ICONEXCLAMATION); break; } if ( DisconnectNamedPipe( hPipe )==0) { MessageBox (NULL, "Disconnect to pipe failed", "Message", MB_OK | MB_ICONEXCLAMATION); break; } } CloseHandle ( hPipe ); return 0; }
Also nochmal:
1. Ich möchte einen Server schreiben, der Daten an die Clients sendet.
diese können dann antorten oder sie werden ferngesteuert, erledigen Aufgaben
2. Muß ich dazu die Endloschleife rausnehmen und die Logik komplett umstellen,
und jedesmal dann die Threads erzeugen, sobald ich neue Daten senden will,
diese schreiben dann an angeschlossene Clients die Nachricht und die Threads
werden dann beendet. mit der nächsten Nachricht (...neue eingeben und auf
Senden klicken...) geschient dann das gleiche Threads erzeugen ....
Oder geht das auch einfacher? Oder macht man daß so gar nicht?Gruß
Franky
-
Ich verstehe Dein Problem nicht ganz.
Wenn die Verbindung zwischen Client und Server besteht kann, doch jeder senden und schreiben wie er will.
Am besten lagert man das in einen eigenen Thread aus und verwendet Overlaped I/O damit man vernünftig den Thread auch beenden und steuern kann.Bei Dir sehe ich Non-Overlapped I/O, as ganze macht das sehr statisch.
-
Hallo,
ich bin blutiger C++ Anfänger und ich hatte versucht, das in VBA zu lösen nur
schloss dann die Anwedung mit einem Fehler. Wenn ich ConnectNamedPipe ausführte, dann stand die Applikation, weil sie auf den Client gewartet hat, gleiches gilt auch für den Client, wenn der Daten sendet und empfängt.
Darum habe ich dann den Code in eine DLL ausgelagert, weil zumindest dort die Threads laufen ohne das sich die Anwendung aufhängt. Mit Overlapped I/O komme ich nicht so klar.Mein Problem ist aber, das mit dem Verbindugsaufbau: Ob Thread oder Anwendung, wie kann man den vernünfig steuern (Von beiden Seiten : Client <-> Server). Weil sonst wartet der Thread bis zun Weltuntergang.
Gibt es da irgendwelche Beispiele? Ist denn die DLL mit dem Thread so Ok, oder gbit es da Probleme?
Gruß
Franky
-
FrankTheFox schrieb:
Mein Problem ist aber, das mit dem Verbindugsaufbau: Ob Thread oder Anwendung, wie kann man den vernünfig steuern (Von beiden Seiten : Client <-> Server). Weil sonst wartet der Thread bis zun Weltuntergang.
wenn der thread hängt, im ConnectNamedPipe oder ReadFile, WriteFile, dann brauchste einfach nur von aussen das pipe-handle schliessen. die funktionen kommen dann mit 'nem fehler raus und in dem fall du auch gleich den thread beenden. overlapped i/o brauchste nicht zu machen, wenn du für die verbindung threads benutzt...
-
Hallo,
wenn ich Pipeserver und Client auf einem Rechner habe, kann ich einen Event erzeugen und mit WaitForMulripleObjects dann warten bis das Event (Flag) in den signalisierenden Zustand übergeht, da aber die Kommunikation über das Netzwerk erfolgen soll (nicht nur lokal): Warte ich dann mit WaitForMutipleObjects auf die Pipes....?
Gruß
Franky
-
man braucht keine extra events zum warten.
der server wartet im 'ConnectNamedPipe' bis ein client da ist, oder die pipe geschlossen wird.
clients können 'WaitNamedPipe' benutzen, um auf das 'ConnectNamedPipe' des servers zu warten.
wenn du dafür threads nimmst, bremst das auch nicht den rest den programms...
guckst du: http://msdn2.microsoft.com/en-us/library/aa365799.aspx
-
FrankTheFox schrieb:
wenn ich Pipeserver und Client auf einem Rechner habe, kann ich einen Event erzeugen und mit WaitForMulripleObjects dann warten bis das Event (Flag) in den signalisierenden Zustand übergeht, da aber die Kommunikation über das Netzwerk erfolgen soll (nicht nur lokal): Warte ich dann mit WaitForMutipleObjects auf die Pipes....?
Beschäftige Dich erst mal mit Overlapped I/O. Schau Dir das Beispiel an, dass ten Dir gegeben hat. Da ist alles drin was Du brauchst.
Dieser Code blockiert ncihts und ist gleichzeitig ein guter Anfang für Muliththreaded Named Pipe Server/Clients.
-
Hallo,
danke für die Hilfestellung, ich werde mir das Beispiel von Ten ansehen und auch Overlapped I/O. Sobald ich dann die DLL fertig habe oder noch Fragen, werde ich sie posten!
Nur eiue klitzekleine Frage. Wie müßte ich die DLL aufbauen, um Änderungen an meinen Puffer (also die Daten, die ich senden möchte vom Server) zu ermöglichen.
Also ich sende vom Server Daten1, dann möchte ich Daten2 senden, ......
Und woher weiß ich wann meine Daten erfolgreich gesendet wurden?
Müssen dann die Clienttrheads komplett abgearbeitet sein und ich müss, falls ich dann neune Daten sende, neue Threads erzeugen (um das Beispiel aufzugreifen, das ich schon gepostet habe....)Ich hoffe ich muß bicht auch noch eine .ocx Datei erstellen, abeer ich glube in eine DLL, die ja nur eine Funktionsammlung ist wird das wohl nicht gehen.
Gruß
Frank
-
Hallo,
aber der Code (Microsoft, oder mycplus.com/...) benutzen zur Steuerung CreateEvent
Aber ich kann das doch so nicht über ein Netzwerk angehen?Gruß
Franky
-
1. Deine Daten kannst Du als geschrieben ansehen, wenn WriteFile returniert! D.h. nicht, dass die Daten auch schon gelesen sind. Wenn Du willst das keine neuen Daten geschrieben werden bevor die alten bearbeitet wurden, dann musst Du Dir ein eigenes Protokoll für Deine Pipe ausdenken mit Befehl-Antwort Struktur.
2. CreateEvent ist doch nur intern auf der Maschine für den Overlapped I/O nötig. Was über das Netzwerk passiert macht die Pipe selber mit dem anderen Server/Client aus...
Ich empfehle Dir nochmal. Lies das Beispiel und probiere es aus!
Das geht auch über ein Netzwerk hinweg!