🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
3 messages
3 total messages Started by T. Meyer Thu, 17 Aug 2006 14:17
NamedPipe problem
#3281
Author: T. Meyer
Date: Thu, 17 Aug 2006 14:17
223 lines
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
#3282
Author: Remy Lebeau (TeamB)
Date: Thu, 17 Aug 2006 16:59
70 lines
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
#3283
Author: mr. Burns
Date: Thu, 17 Aug 2006 18:02
25 lines
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