Thread View: borland.public.cppbuilder.nativeapi
3 messages
3 total messages
Started by T. Meyer
Thu, 17 Aug 2006 14:17
NamedPipe problem
Author: T. Meyer
Date: Thu, 17 Aug 2006 14:17
Date: Thu, 17 Aug 2006 14:17
223 lines
7484 bytes
7484 bytes
Hello,
I have a problem on my NamedPipe application.
my NamedPipe server works well, it receives the message from client and
sends back a message a message to the client.
But with the client I have a problem.
The client should read the response from the server, but everytime I get:
The handle is invalid!
I use an overlapped structure to don't block my client.
So the 1st question is: Why writing to the server wokrs but reading (over
same pipe) causes: 'The handle is invalid!'?
My 2nd qustion is, I use overlapped IO to ensure my program can do further
things if pipe reading not finsihed at once.
But I dont know the WHEN the reading is complete.
if ReedFile returns back I catch the error code to get information what
happend.
If error code is ERROR_IO_PENDING the I use WaitForMultipleObjects and
GetOverlappedResult but then I do not know
what is the trigger to say ReadFile has finsihed the reading?
Here is my code:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "SyncObjs.hpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define BUFSIZE 512
TForm1 *Form1;
TEvent *PipeEvt;
HANDLE hEvents[1];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
PipeEvt = new TEvent(NULL, true, true, NULL);
hEvents[0] = (HANDLE)PipeEvt->Handle;
OL.Offset = 0;
OL.OffsetHigh = 0;
OL.hEvent = PipeEvt;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ApplicationRunning = true;
HANDLE hPipe;
LPTSTR lpvMessage=TEXT("Default message from client");
TCHAR chBuf[BUFSIZE];
BOOL fSuccess;
DWORD cbRead, cbWritten, dwMode, dwWait;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
// Try to open a named pipe; wait for it, if necessary.
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)
{
ShowMessage("Could not open pipe");
exit(-1);
}
// All pipe instances are busy, so wait for 20 seconds.
if (!WaitNamedPipe(lpszPipename, 20000))
{
ShowMessage("Could not open pipe");
exit(-1);
}
Application->ProcessMessages();
}
// 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)
{
ShowMessage("SetNamedPipeHandleState failed");
exit(-1);
}
// Send a message to the pipe server.
fSuccess = WriteFile(
hPipe, // pipe handle
lpvMessage, // message
(lstrlen(lpvMessage)+1)*sizeof(TCHAR), // message length
&cbWritten, // bytes written
NULL); // NULL for not overlapped
if (!fSuccess)
{
ShowMessage("WriteFile failed");
exit(-1);
}
/*
do
{
// Wait infinitively until server sends an response
// Read from the pipe.
fSuccess = ReadFile(
hPipe, // pipe handle
chBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
NULL); // NULL for not overlapped, means wait infinitively
if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
break;
Memo1->Lines->Add(chBuf);
} while (!fSuccess); // repeat loop if ERROR_MORE_DATA
*/
bool ReadCompleted = false;
fSuccess = ReadFile(
hPipe, // pipe handle
chBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
&OL); // NULL if not overlapped
if (!fSuccess)
{
// ReadFile not completed, so wait until PipeEvt signaled
DWORD cbRet, dwErr, dwRet;
dwErr = GetLastError();
if (dwErr != ERROR_IO_PENDING)
{
ShowError(dwErr); // <-------------------------------- Everytime my
programs stops here with The handle is invalid! Why?
}
else
{
while(!ReadCompleted)
{
static int i = 0;
dwWait = WaitForMultipleObjects(
1, // number of event objects
hEvents, // array of event objects
FALSE, // does not wait for all
1000); // wait 1 sec.
switch (dwWait)
{
case WAIT_TIMEOUT: Memo1->Lines->Add(IntToStr(i));
break;
case WAIT_OBJECT_0: dwRet = GetOverlappedResult(
hPipe, // handle to pipe
&OL, // OVERLAPPED structure
&cbRet, // bytes transferred
FALSE); // do not wait
PipeEvt->ResetEvent();
break;
// ------------------------------------------------When is the
ReadFile completed to set ReadCompleted to true to leave this loop?
}
Application->ProcessMessages();
}
}
}
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ShowError(DWORD Err)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
Application->MessageBox((char*)lpMsgBuf, "GetLastError", MB_OK |
MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
}
//---------------------------------------------------------------------------
Re: NamedPipe problem
Author: Remy Lebeau (TeamB)
Date: Thu, 17 Aug 2006 16:59
Date: Thu, 17 Aug 2006 16:59
70 lines
3486 bytes
3486 bytes
"T. Meyer" <timon@mustek.de> wrote in message
news:44e47a8e$1@newsgroups.borland.com...
> Why writing to the server wokrs but reading (over same pipe)
> causes: 'The handle is invalid!'?
You did not specify FILE_FLAG_OVERLAPPED when calling CreateFile().
> I use overlapped IO to ensure my program can do
> further things if pipe reading not finsihed at once.
> But I dont know the WHEN the reading is complete.
The is what the TEvent is for. It is signaled when an overlapped operation
is finished. You can then call GetOverlappedResult() to get the result of
the operation.
> if ReadFile returns back I catch the error code to get information
> what happend. If error code is ERROR_IO_PENDING the I use
> WaitForMultipleObjects and GetOverlappedResult but then I do
> not know what is the trigger to say ReadFile has finsihed the reading?
Yes, you do, because you are already waiting for the reading to finish.
When WaitForMultiObjects() returns WAIT_OBJECT_0, the event has been
signaled, and then you are calling GetOverlappedResult() to get the result
of the reading.
Why are you using WaitForMultipleObjects() for a single object? Use
WaitForSingleObject() instead. Better yet, TEvent has its own WaitFor()
method that you can use.
> exit(-1);
DO NOT use exit() in a VCL application! It does not allow the VCL to clean
up after itself on shutdown. Use Application->Terminate() instead, or
alternatively just Close() the MainForm.
You are also leaking all of the objects and handles that you created.
Always free your objects, and close your handles.
> // Send a message to the pipe server.
> fSuccess = WriteFile(
Why are you trying to use Overlapped I/O for reading but not for writing?
Writing has just as much a chance of blocking as reading does. In fact, if
you want to use Overalpped I/O for reading, then you have to specify
FILE_FLAG_OVERLAPPED in CreateFile(), which in turn will require that you
use Overlapped I/O for WriteFile() as well. WriteFile() will fail if you
don't pass it an OVERLAPPED structure for a file handle that uses Overlapped
I/O.
> When is the ReadFile completed to set ReadCompleted to true to leave this
loop?
When the event has become signaled, causing WaitFor...() to return
WAIT_OBJECT_0.
> void __fastcall TForm1::ShowError(DWORD Err)
You don't need to call FormatMessage() yourself. The VCL has its own
SysErrorMessage() function that does that for you.
void __fastcall TForm1::ShowError(DWORD Err)
{
Application->MessageBox(SysErrorMessage(Err).c_str(),
"GetLastError", MB_OK | MB_ICONINFORMATION);
}
Gambit
Re: NamedPipe problem
Author: mr. Burns
Date: Thu, 17 Aug 2006 18:02
Date: Thu, 17 Aug 2006 18:02
25 lines
2180 bytes
2180 bytes
Hello Gambit, thanks for your help! My application I have shown is not complete up to now, so I already know about the exit() issue and I also miss in this state to free the handles. It is not the final version just a scrapbook where I can test and learn more about named pipes. So give free the handles and replace the exit() will come on refining later. But thanks anyway for your help on these issues! Up to now I did not really understand what the GetOverlappedResult() function is for. I just want to let read my client a certain No. of bytes and if this is not finsihed e.g. in 20 seconds my program should show an error message. But in this 20 seconds I want to do something useful and not block my application. Lets say I use now the WaitForSingleObject() function. You said that the overlapped ReadFile function signals the event when reading is finished. Then I just have to code e.g. ShowMessage(InBuf) in the WAIT_OBJECT_0 case to catch the complete transmitted data, or not? So for what now is the GetOverlappedResult() function? What does it do? When do I have to call it? How many bytes maximum I can transmit using named pipes? Is there any limit? Thanks for further information!
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads