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