AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

NamedPipe @Buffer[0] exception

Ein Thema von Corelgott · begonnen am 17. Aug 2009 · letzter Beitrag vom 17. Aug 2009
Antwort Antwort
Benutzerbild von Corelgott
Corelgott

Registriert seit: 11. Apr 2003
Ort: Lübeck
213 Beiträge
 
Delphi 2006 Enterprise
 
#1

NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 11:09
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:
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;
Der Client macht dann folgendes:

Delphi-Quellcode:
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;
Der Host läuft in seinem eigenen thread und überprüft ob Daten vorhanden sind via:

Delphi-Quellcode:
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;
Nun kommt das problem: das auslesen:
Delphi-Quellcode:

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;
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...

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
wer Rächtschraibfehler findet daaf sie behalten...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#2

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 11:12
Zitat:
Delphi-Quellcode:
procedure TCustomPipe.cleanBuffer();
begin
  // resize & init
  setLength(FBuffer, buffersize);
  FillChar(self.FBuffer[0], length(self.FBuffer), #0);
end;
Müsste das nicht eher
Delphi-Quellcode:
procedure TCustomPipe.cleanBuffer();
begin
  // resize & init
  setLength(FBuffer, buffersize);
  FillChar(self.FBuffer, length(self.FBuffer), #0);
end;
heißen?
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 11:20
@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]
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;
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Corelgott
Corelgott

Registriert seit: 11. Apr 2003
Ort: Lübeck
213 Beiträge
 
Delphi 2006 Enterprise
 
#4

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 11:53
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
wer Rächtschraibfehler findet daaf sie behalten...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 12:06
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 von Corelgott:
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)
tja, dann bleiben grundsätzlich noch 2 Progleme, entweder der Puffer ist zu klein und es wird drüberrausgeschrieben, oder mit der Array-Variable stimmt etwas nicht.

ich würde da wohl eher mal auf Ersteres tippen
> 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 ,
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)
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Corelgott
Corelgott

Registriert seit: 11. Apr 2003
Ort: Lübeck
213 Beiträge
 
Delphi 2006 Enterprise
 
#6

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 12:43
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
Angehängte Dateien
Dateityp: zip apppipe_799.zip (28,2 KB, 6x aufgerufen)
wer Rächtschraibfehler findet daaf sie behalten...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 13:02
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:
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();
PS: du hast in der Prozedur zwar den Parameter data definiert, weißt diesem aber nix zu

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)
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Corelgott
Corelgott

Registriert seit: 11. Apr 2003
Ort: Lübeck
213 Beiträge
 
Delphi 2006 Enterprise
 
#8

Re: NamedPipe @Buffer[0] exception

  Alt 17. Aug 2009, 13:25
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
Angehängte Dateien
Dateityp: zip apppipe_663.zip (28,2 KB, 8x aufgerufen)
wer Rächtschraibfehler findet daaf sie behalten...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz