|
Registriert seit: 17. Jul 2007 Ort: Ulm 258 Beiträge Delphi 7 Enterprise |
#1
Guten Tag,
Ich schlage mich gerade mit einem merkwürdigen Problem rum..und zwar: Ich habe eine DLL in c++ und eine Anwendung in delphi. Dieses zwei sollen mittels Pipes kommunizieren. In diesem Fall ist die Anwendung der Server und die DLL der/die Client/s. Server-Klasse:
Delphi-Quellcode:
Die C++ DLL:
unit TPipeServerU;
interface uses Classes, Windows, SysUtils, Dialogs; type TPipeMessage = record size : DWORD; dataSize : DWORD; header : Byte; subheader : Byte; data : array[0..511] of char; end; TPipeServer = class(TThread) private FHandle: THandle; FPipeName: String; protected public constructor CreatePipeServer(aServer, aPipe: String; StartServer: Boolean); destructor Destroy; override; procedure StartUpServer; procedure ShutDownServer; procedure Execute; override; end; TPipeClient = class(TThread) private FHandle: THandle; protected public constructor CreatePipeClient(handle: THandle); procedure Execute; override; end; const cShutDownMsg = 'shutdown pipe '; cPipeFormat = '\\%s\pipe\%s'; implementation constructor TPipeServer.CreatePipeServer( aServer, aPipe: String; StartServer: Boolean ); begin if aServer = '' then FPipeName := Format(cPipeFormat, ['.', aPipe]) else FPipeName := Format(cPipeFormat, [aServer, aPipe]); // clear server handle FHandle := INVALID_HANDLE_VALUE; if StartServer then StartUpServer; // create the class Create(not StartServer); end; destructor TPipeServer.Destroy; begin if FHandle = INVALID_HANDLE_VALUE then // must shut down the server first ShutDownServer; inherited Destroy; end; procedure TPipeServer.Execute; var I, Written: Cardinal; InMsg, OutMsg: TPipeMessage; begin while not Terminated do begin if FHandle = INVALID_HANDLE_VALUE then begin // suspend thread for 250 milliseconds and try again Sleep(250); end else begin if ConnectNamedPipe(FHandle, nil) then TPipeClient.CreatePipeClient(FHandle); end; end; end; procedure TPipeServer.ShutDownServer; var BytesRead: Cardinal; OutMsg, InMsg: TPipeMessage; ShutDownMsg: String; begin if not FHandle = INVALID_HANDLE_VALUE then begin { // server still has pipe opened OutMsg.Size := SizeOf(OutMsg); // prepare shut down message with InMsg do begin Kind := 0; ShutDownMsg := cShutDownMsg + FPipeName; Count := Succ(Length(ShutDownMsg)); StrPCopy(Data, ShutDownMsg); // end; CalcMsgSize(InMsg); // send shut down message CallNamedPipe( PChar(FPipeName), @InMsg, InMsg.Size, @OutMsg, OutMsg.Size, BytesRead, 100 ); } // close pipe on server CloseHandle(FHandle); // clear handle FHandle := INVALID_HANDLE_VALUE; end; end; procedure TPipeServer.StartUpServer; begin // check whether pipe does exist if WaitNamedPipe(PChar(FPipeName), 100 {ms}) then raise Exception.Create('Requested PIPE exists already.'); // create the pipe FHandle := CreateNamedPipe( PChar(FPipeName), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, SizeOf(TPipeMessage), SizeOf(TPipeMessage), NMPWAIT_USE_DEFAULT_WAIT, nil ); // check if pipe was created if FHandle = INVALID_HANDLE_VALUE then raise Exception.Create('Could not create PIPE.'); end; { TPipeClient } procedure TPipeClient.Execute; var I, Written: Cardinal; InMsg: TPipeMessage; fSucess: Boolean; begin fSucess := false; //ShowMessage('Client executing'); while(true) do begin InMsg.Size := SizeOf(InMsg); fSucess := ReadFile(FHandle, InMsg, InMsg.Size, InMsg.Size, nil); if(fSucess) then begin if (InMsg.header = 01) then begin if (InMsg.subheader = 02) then ShowMessage('Size: '+IntToStr(InMsg.dataSize)+' Msg[0]: '+ IntToHex(integer(InMsg.data[511]), 2)); end; end; Sleep(100); end; end; constructor TPipeClient.CreatePipeClient(handle: THandle); begin FHandle := handle; Create(false); end; end.
Code:
Das Problem ist, wenn ich mit einem 2. Client Versuche zu verbinden scheitert es am
DWORD WINAPI Pipe_Thread( LPVOID lpParam )
{ HANDLE hPipe; LPTSTR lpvMessage=TEXT("Default message from client."); TCHAR chBuf[512]; BOOL fSuccess = FALSE; DWORD cbRead, cbToWrite, cbWritten, dwMode; LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\testit"); TPipeMessage Packet; while (1) { hPipe = CreateFile( lpszPipename, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file // Break if the pipe handle is valid. if (hPipe != INVALID_HANDLE_VALUE) break; // Exit if an error other than ERROR_PIPE_BUSY occurs. if (GetLastError() != ERROR_PIPE_BUSY) { //_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); return -1; } // All pipe instances are busy, so wait for 20 seconds. if ( ! WaitNamedPipe(lpszPipename, 20000)) { MessageBox(HWND_DESKTOP,"Blabla2","Titel",MB_OK); //printf("Could not open pipe: 20 second wait timed out."); return -1; } } // The pipe connected; change to message-read mode. dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState( hPipe, // pipe handle &dwMode, // new pipe mode NULL, // don't set maximum bytes NULL); // don't set maximum time if ( ! fSuccess) { // _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); return -1; } // Send a message to the pipe server. cbToWrite = sizeof(Packet); //Packet.size = sizeof(Packet); Packet.data[0] = 0xAA; Packet.data[511] = 0xBB; Packet.dataSize = 512; Packet.header = 0x01; Packet.subheader = 0x02; fSuccess = WriteFile( hPipe, // pipe handle &Packet, // message cbToWrite, // message length &cbWritten, // bytes written NULL); // not overlapped sprintf(chBuf, "Bytes sent %i", cbWritten); MessageBox(HWND_DESKTOP,chBuf,"SsS2",MB_OK); if ( ! fSuccess) { //_tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); return -1; } //printf("\nMessage sent to server, receiving reply as follows:\n"); /* do { // Read from the pipe. fSuccess = ReadFile( hPipe, // pipe handle chBuf, // buffer to receive reply 512*sizeof(TCHAR), // size of buffer &cbRead, // number of bytes read NULL); // not overlapped if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA ) break; } while ( ! fSuccess); // repeat loop if ERROR_MORE_DATA if ( ! fSuccess) { //_tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() ); return -1; } printf("\n<End of message, press ENTER to terminate connection and exit>"); _getch(); */ while(hPipe); CloseHandle(hPipe); return 0; }
Code:
Wo ist mein Fehler?
if ( ! WaitNamedPipe(lpszPipename, 20000))
Ich hab mir die Multithread-Server Idee von MSDN geklaut. Dort wird jedesmal nach ConnectNamedPipe() ein neuer Thread erstellt, der thread wartet dann auf nachrichten vom jeweiligen Client. Der Thread erhält den hPipe parameter und nutzt dieses um auf nachrichten des client abzuwarten bzw diese mittels ReadFile() auszulesen. Doch der aufruf von ConnectNamedPipe() ändert ja nichts am hPipe handle..so wundere ich mich wie solch ein server-thread den client überhaupt identifizieren kann. Liebe Grüße Timo Maier Edit: Außerdem ist mir aufgefallen, dass das Empfangen der Nachricht nur sporadisch funktioniert. Manchmal wird beim empfangen der nachricht auf der Serveranwendung in der ShowMessage() nur ein leeres Fenster angezeigt. Doch die header und subheader prüfung funktioniert... Edit2: Ok hat sich erledigt. Hab übersehen das man für jeden Client ein neues PipeHandle via CreateNamedPipe() erstellen muss. Geändert von k4ni (24. Aug 2013 um 10:38 Uhr) |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |