![]() |
Senden an Named Pipe klappt nicht! Warum? [erledigt]
Hallo,
Ich experimentiere soeben mit Named Pipes. Leider klappt die Datenübertragung nicht und ich habe keine Ahnung, wo ich meinen Fehler suchen müsste. Wer kann mir helfen. Hier erst mal mein Quelltext:
Delphi-Quellcode:
In einer späteren praktischen Anwendung würde ich den Pipeserver vom Client aus vorher starten.
//Hier erst mal der Pipe-Server, den ich später mit Kommandos steuern will.
program PipedProcess; uses Sysutils, {$ifdef WIN32} Windows {$else} {$ifdef LINUX} libc, linux {$endif} {$endif} ; {$APPTYPE CONSOLE} const BytePipe = PIPE_TYPE_BYTE or PIPE_READMODE_BYTE; MessagePipe = PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE; ONE_INSTANCE = 1; MAX_INSTANCE = PIPE_UNLIMITED_INSTANCES; PIPE_NAME = '\\.\pipe\testpipe'; type PInputBuffer = ^TInputBuffer; TInputBuffer = record Signature: String[7]; Value: Longint; end; var Hpipe: THandle; lpPipeName: PChar; OpenMode: DWord; PipeMode: DWord; MaxInstances: DWord; OutBufSize: DWord; InpBufSize: DWord; Buffer: TInputBuffer; BufferPtr: PInputBuffer; Readed: Boolean; WasReaded: DWord; Written: DWord; AOverlapped: POverlapped; begin MaxInstances := 1; Readed := false; HPipe := CreateNamedPipe('\\.\pipe\testpipe', PIPE_ACCESS_DUPLEX {or FILE_FLAG_OVERLAPPED}, PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT, 1, //max instances of this pipe SizeOf(Buffer), SizeOf(Buffer), 0, //if 0 -> 50ms else X ms nil ); Getmem(AOverlapped, Sizeof(_OVERLAPPED)); FillChar(AOverlapped^, Sizeof(_OVERLAPPED), $00); ConnectNamedPipe(HPipe, AOverlapped); Getmem(Bufferptr, Sizeof(Buffer)); BufferPtr^.Signature := ''; BufferPtr.Value := 0; repeat {if not readed then} ReadFile(HPipe, Buffer, Sizeof(Buffer), WasReaded, nil); //nil statt AOverlapped BufferPtr := @Buffer; Readed := true; case Buffer.Value of 1: begin WriteFile(HPipe, BufferPtr, Sizeof(Buffer), Written, nil); //nil statt AOverlapped write(BufferPtr^.Value); Write(' '); Write(BufferPtr^.Signature); Write(' '); end; 2: Readed := false; 3: ; end; until Buffer.Signature = '1234567'; Freemem(Bufferptr, Sizeof(Buffer)); Freemem(AOverlapped, Sizeof(_OVERLAPPED)); CloseHandle(HPipe); end. //============================================================================================= //============================================================================================= //Und hier der Pipe-Client, von dem aus die Steuerung erfolgt: unit CodeTemplates; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; const BytePipe = PIPE_TYPE_BYTE or PIPE_READMODE_BYTE; MessagePipe = PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE; ONE_INSTANCE = 1; MAX_INSTANCE = PIPE_UNLIMITED_INSTANCES; PIPE_NAME = '\\.\pipe\testpipe'; type PInputBuffer = ^TInputBuffer; TInputBuffer = record Signature: String[7]; Value: Longint; end; TPipeForm = class(TForm) edCmd: TEdit; Label1: TLabel; Label2: TLabel; edValue: TEdit; btnTransfer: TButton; Label3: TLabel; lblReceive: TLabel; lblValue: TLabel; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btnTransferClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var PipeForm: TPipeForm; HPipe: THandle; lpPipeName: PChar; OpenMode: DWord; PipeMode: DWord; MaxInstances: DWord; OutBufSize: DWord; InpBufSize: DWord; Buffer: TInputBuffer; BufferPtr: PInputBuffer; Readed: Boolean; WasReaded: DWord; Written: DWord; AOverlapped: POverlapped; implementation {$R *.dfm} procedure TPipeForm.FormDestroy(Sender: TObject); begin Freemem(AOverlapped, Sizeof(_OVERLAPPED)); end; procedure TPipeForm.FormCreate(Sender: TObject); 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; HPipe := CreateFile(PChar('\\.\pipe\testpipe'), GENERIC_READ or GENERIC_WRITE, 0, @FSA, OPEN_EXISTING, 0, 0); Getmem(AOverlapped, Sizeof(_OVERLAPPED)); FillChar(AOverlapped^, Sizeof(_OVERLAPPED), $00); end; procedure TPipeForm.btnTransferClick(Sender: TObject); var receive: Boolean; dw,dr: DWord; begin Buffer.Signature := edCmd.Text; Buffer.Value := StrToInt(edValue.Text); receive := (Buffer.Value = 1); WriteFile(HPipe, Buffer, SizeOf(Buffer), dw, nil); if receive then begin ReadFile(HPipe, Buffer, SizeOf(Buffer), dr, nil); end; lblReceive.Caption := Buffer.Signature; lblValue.Caption := IntToStr(Buffer.Value); end; end. Hier habe ich ihn vor Start meines Pipeclients gestartet. Ich habe darauf vertraut, das der Name der Pipe irgendwo in Windows eingetragen ist und so auch gefunden wird. Ich will die hier entwickelte Lösung später, wenn alles nach Wunsch läuft, für die Kommunikation von Programmen verschiedener Programmiersprachen oder Sprachdialekte verwenden, weshalb ich mich dabei bewusst auf das Windows API beschränke, in der Hoffnung, so die portabelste Lösung innerhalb der Windows Plattform für die unterschiedlichen Programmiersprachen zu erhalten. Was muss ich hier anders machen, damit die Kommunikattion gelingt. Mein Server sollte wenigstens, wenn ich den Wert 1 übegebe, eine 1 auf der Windows Console ausgeben. Wie kann ich später die Console unsichtbar machen. Die brauche ich ausschließlich für den Test und die Entwicklung meiner Lösung. |
Re: Senden an Named Pipe klappt nicht! Warum?
1. Der Name muss dem Schema "\\.\pipe\mynamedpipe" entsprechen
2. warum definierst du TInputBuffer mehrmals? 3. Die overlapped struktur wurde nicht initialisiert |
Re: Senden an Named Pipe klappt nicht! Warum?
Zitat:
Zitat:
Zitat:
und durch Fillchar() mit $00 initialisiert. Leider kommt auf der sichtbaren Console noch immer nix an. Was kann ich jetzt noch machen? ConnectNamedPipe ist false und so komme ich natürlich niemals zum lesen oder schreiben der Pipe. |
Re: Senden an Named Pipe klappt nicht! Warum?
Du musst im Server ConnectNamedPipe aufrufen nicht im client. Im client verwendest du createFile statt createnamedpipe.
Schau dir am besten mal die beispiele im msdn an. http://msdn.microsoft.com/en-us/library/aa365592(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa365603(VS.85).aspx Das overlapped würde ich am anfang mal weglassen, um dies als Fehlerquelle auszuschließen (zumal du da noch mehr machen müsstest als du jetzt hast). |
Re: Senden an Named Pipe klappt nicht! Warum?
Hallo Hermes!
Jetzt klappt zumindest die Übertragung vom Client zum Pipeserver. Ich kann in der Konsole meine übertragenen Daten sehen. Danke! :hello: Nur vom Server zum Client will es noch nicht klappen. Der Einfachheit halber habe ich die obigen Quelltexte gleich an der zentralen Stelle aktualisiert. So wie oben sichtbar sehen meine Quellen jetzt aus. Warum kann ich keine Daten vom Server an den Client senden? :gruebel: Dazu werd ich aber mal besser einen neuen Thread eröffnen, wie es die Nutzungsbedingungen hier vorsehen. Der ist hier zu finden: ![]() Vielleicht hat ja jemand anderes mal das gleiche Problem. Ein anderes Phänomen ist: Ich erhalte, wenn ich die Zeichenfolge "1234567" an Buffer.Signature übergebe das Windows Fenster mit der Mitteilung "pipedprocess hat ein Problem festgestellt und muss beendet werden" und die Buttons <Senden> <Nicht senden> Mit der Zeichenfolge "1234567" will ich aber den Pipeserver regulär beenden. Das Kommando dazu ist die besagte Zeichenfolge, womit das Beenden des Prozesses gewollt ist. Wenn ich nur den Client beende, ohne vorher das besagte Kommando gesendet zu haben, bleibt der Server aktiv. Somit muss ich ihn entweder nach Schließen des Clients separat beenden oder vor Beenden des Clients das Kommando zum Beenden des Servers senden. Aber warum dann die Fehlermeldung von Windows? :gruebel: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:36 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