![]() |
NamedPipe @Buffer[0] exception
Hi @ all,
ich quäle mich schon seit Tagen mit der Kommunikation per Named Pipes. An sich ist das ja nicht weiter schwer aber: Ich habe das Problem, dass ich grundsätzlich beim 2. Versuch von Client zum Host etwas zu übermitteln eine Exception bekomme... Mein Host sieht so aus:
Delphi-Quellcode:
Der Client macht dann folgendes:
function TPipeHost.createConnection(pipeName: string): HWND;
var FSA : SECURITY_ATTRIBUTES; FSD : SECURITY_DESCRIPTOR; verbs : Cardinal; Mode : Cardinal; begin self.FPipeName := pipeName; verbs := PIPE_TYPE_BYTE or PIPE_WAIT or PIPE_READMODE_BYTE; InitializeSecurityDescriptor(@FSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(@FSD, True, nil, False); FSA.lpSecurityDescriptor := @FSD; FSA.nLength := sizeof(SECURITY_ATTRIBUTES); FSA.bInheritHandle := True; result := CreateNamedPipe(PChar('\\.\pipe\' + pipeName), PIPE_ACCESS_DUPLEX, verbs, PIPE_UNLIMITED_INSTANCES, buffersize, buffersize, NMPWAIT_USE_DEFAULT_WAIT, nil); if isConsole then writeln(Format('Created Pipe with handle: %d', [result])) end;
Delphi-Quellcode:
Der Host läuft in seinem eigenen thread und überprüft ob Daten vorhanden sind via:
function TPipeClient.createConnection(pipeName: string): HWND;
var FSA : SECURITY_ATTRIBUTES; FSD : SECURITY_DESCRIPTOR; begin InitializeSecurityDescriptor(@FSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(@FSD, True, nil, False); FSA.lpSecurityDescriptor := @FSD; FSA.nLength := sizeof(SECURITY_ATTRIBUTES); FSA.bInheritHandle := True; self.FPipeName := pipeName; result := CreateFile(PChar('\\.\pipe\' + pipeName), GENERIC_READ or GENERIC_WRITE, PIPE_TYPE_BYTE, @FSA, OPEN_EXISTING, 0, 0); if isConsole then writeln(Format('Connected to Pipe with handle: %d', [result])) end;
Delphi-Quellcode:
Nun kommt das problem: das auslesen:
function TCustomPipe.dataAvailable: Cardinal;
var readCount : LongWord; rest : LongWord; begin result := 0; rest := 0; readCount := 0; // get data from pipe if self.hasValidHandle() then PeekNamedPipe(self.getHandle(), @self.FBuffer[0], BufferSize, @readCount, @rest, nil); result := rest; end;
Delphi-Quellcode:
Was Mache ich falsch? Darf ich kein Array of Byte übergeben? Was ich bei dem Thread nicht tue ist nach jedem Lesen die datei wieder zu schließen... Wie das in so vielen Beispielen gemacht wird...type TPipeHost strict private FBuffer : TByteDynArray; // [.... snip .... ] procedure TCustomPipe.cleanBuffer(); begin // resize & init setLength(FBuffer, buffersize); FillChar(self.FBuffer[0], length(self.FBuffer), #0); end; // method to read data procedure TCustomPipe.readData(var data : TByteList); var dataCount : Cardinal; dataRead : Cardinal; callBack : Pointer; begin dataRead := 0; dataCount := self.dataAvailable(); // hwnd <> 0 && hwnd <> INVALID_HANDLE if self.hasValidHandle then begin EnterCriticalSection(self.FSection); // got data? while(dataCount > 0) do begin try self.cleanBuffer(); (* Hier kommt das Problem: ReadFile verändert mir die Größe meines Dyn-Array (!?!) und ne Access-Voilation-Exception (Was ein wunder, wenn die API das Array kaputt macht...) Sowie ich self.FBuffer[0] übergebe bekomme ich 1. Nur noch mist an Daten & 2. Ne tolle Exception *) ReadFile(self.getHandle(), self.FBuffer, dataCount, dataRead, nil); // process data // look if there is any new data left dataCount := self.dataAvailable(); finally // dispose buffer setLength(buffer, 0); end; end; LeaveCriticalSection(self.FSection); end; end; Hat wer nen Tipp für mich? Oder vielleicht ein Beispiel? Ich hatte leider bei Lunkie nix gefunden und auch meine Google Exkursionen waren nicht gerade erfolgreich. Die Forum-Suche brachte auch nichts zu tage, was meinen effekt auch nur ansatzweise erklären könnte? Schon mal vielen Dank für's Nachdenken im Voraus! Gruß Corelgott |
Re: NamedPipe @Buffer[0] exception
Zitat:
Delphi-Quellcode:
heißen?
procedure TCustomPipe.cleanBuffer();
begin // resize & init setLength(FBuffer, buffersize); FillChar(self.FBuffer, length(self.FBuffer), #0); end; |
Re: NamedPipe @Buffer[0] exception
@FillChar(Self.FBuffer[0]:
nein, ist schon OK so, denn es handelt sich ja um ein dynamisches Array und da würde ohne die [0] auf den Array-Zeiger und nicht auf den Datenbereich gezeigt. welches genau da Progleme macht ... also ohne die [0] :zwinker:
Delphi-Quellcode:
ReadFile(getHandle(), FBuffer[0], ...
PS: warum verwendest du eigentlich so oft Self? wo die darüber referenzierten Namen doch eh in selben/aktuellen Namespace liegen und es keine überlagerten Namen an diesen Stellen gibt. und das Ganze dann auch noch so inkonsequent ... also wenn schon, dann sollte man sowas schon durchgängig gleich behandeln.
Delphi-Quellcode:
procedure TCustomPipe.cleanBuffer();
begin // resize & init setLength({self.}FBuffer, buffersize); <<<<<<< FillChar(self.FBuffer[0], length(self.FBuffer), #0); end; |
Re: NamedPipe @Buffer[0] exception
Hi,
erst mal danke für die Antworten! wegen meines Self-Fimmels, ich weiss, dass es nicht nötig ist, aber ich habe es mir angewöhnt aus anderes Aprachen wie PHP immer den Scope explizit zu benennen. Dadurch wird das lesen, finde ich zumindest, einfacher und klarer. Gerade wegen der Unart in Delphi With Blöcke zu benutzen... (Wie gesagt, ist ein Tick von mir </Delphi_Synatx_bashing>) Was das self.FBuffer[0] angeht: Das Problem ist, sowie man das macht kommen nur noch unsinnige Daten, die nichts mehr mit dem zu tun haben, was per WriteFile geschickt wurde (+ auch eine Access Violation) Deinen Ansatz kann ich durchaus verstehen, würde für mich auch mehr Sinn machen wenn man self.FBuffer[0] übergeben würde. Eben eine Ref auf das erste Element des Arrays... Nichts desto weniger wird es dann nur noch abenteurlicher... Danke erst mal für die Antworten! Ich bin gerne noch für weitere Ideen offen! Gruß Corelgott |
Re: NamedPipe @Buffer[0] exception
Wie gesagt, ohne die [0] schreibst du, bei einem dynamischen Array, nur in den Speicher des internen Array-Zeigers, welcher ja nur 4 Byte groß ist (Pointer) und die restlichen Daten überschreiben dann entweder andere Variablen/Daten und/oder versuchen in einen nicht reservierten Speicherblock zu schreiben, welches natürlich in einer Exception endet.
Zitat:
ich würde da wohl eher mal auf Ersteres tippen :angel2: > also schau einfach mal, wie sich dataCount und buffersize zueinander verhalten Nja, für mich ist ein übermaß an Self und dergleichen wieder zu unübersichtlich :angel2: , aber es ist auch nicht verkehrt, aber wenn schon, dann sollte man wenigstens es überall gleich machen (also in deinem Fall praktisch immer Self. verwenden und nicht mal so und mal so, denn das ist ja im Grunde total unübersichtlich) |
Re: NamedPipe @Buffer[0] exception
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
**hust** joar man sollte das schon Konsitent machen und nicht nur machmal so mit self und so... Hast ja recht... Ich denke ich lege mal ne Ausgedünnte Version des Projektes bei... Vielleicht findet sich dann noch mehr Ansatz. Wie gesagt, das es ist nur ein Test / Versuchs-Projekt... Also bitte nicht wegen der mangelden Kommentare meckern ;) Gruß Corelgott |
Re: NamedPipe @Buffer[0] exception
hab jetzt grad nicht die Zeit/Möglichkeit hier auch noch etwas zu testen, aber versuch du doch erstmal dieses in TCustomPipe.readData:
Delphi-Quellcode:
PS: du hast in der Prozedur zwar den Parameter data definiert, weißt diesem aber nix zu :zwinker:
self.cleanBuffer();
if dataCount > Length(self.FBuffer) then Raise Exception.CreateFmt('FBuffer ist zu klein (%d < %d)', [Length(self.FBuffer), dataCount]); ReadFile(self.getHandle(), self.FBuffer, dataCount, dataRead, nil); dataCount := self.dataAvailable(); und es ist schon etwas "unökonomisch", wenn innerhalb der Leseschleife vor jede und nach jedem Lesedurchgang der Puffer neu erstellt und wieder freigegeben wird (wenn dieser eine feste Größe hat, dann reicht es doch auch vor/nach der Schleife und nicht immer wieder innerhalb Dieser) |
Re: NamedPipe @Buffer[0] exception
Liste der Anhänge anzeigen (Anzahl: 1)
hi,
nun ja... data ist eine liste von objekten die ich per var in die routine geben... somit muss ich da nichts zuweisen, da ich ja mit dem schon existenten objekt arbeite. Was die Buffergröße angeht: Die ist 512 Byte groß. Aber selbst wenn ich nur 13 Byte sende bekomme ich schon die Probleme. Das es nicht so schön ist, wenn man den Buffer bei jedem Aufruf neu setzt ist unumstrittten. Aber selbst wenn ich das in ner konstankten Größe festlege undn ur einmal initialisiere habe ich die gleiche Problematik. Diese Variante ist auch mehr durch's Testen entstanden, als dass es später so gehandhabt werden soll. Ich habe nun die Version mal auf einen "statischen" 512 Byte-Buffer umgeschrieben... was an dem Effekt nicht viel ändert. Bis auf die Tatsache, dass ich jetzt keine sinnigen Daten mehr bekomme... Gruß Corelgott |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz