A
AckMike
I am trying to write client and server programs that communicate with
named pipes. There is one multithreaded server that handles all of the
requests and multiple multithread clients that make the requests. The
problem is that the client hangs at the WriteFile request when running
under load. All the processes are running on the same box. I am
wondering if there is something I am doing wrong fundamentally.
One thing I am doing that is questionable is opening the pipe on the
server side in Overlapped mode and but not using overlapped mode on the
client side. I don't know if this would cause any problems since they
are on the same box.
If I change the server to open the pipe with a inital pipebuffer of 120
for read and write buffers the client then hangs at the readfile().
Any ideas?
SERVER MAIN:
----------------------
HANDLE hPipe = INVALID_HANDLE_VALUE;
HANDLE hEvents[2] = {NULL, NULL};
HANDLE hServerStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
hEvents[0] = hServerStopEvent;
while (1)
{
OVERLAPPED *pOS = NULL;
hEvents[1] = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
NULL); // no name
// Create the pipe
hPipe = CreateNamedPipe(
szPipeName,
PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
NMPWAIT_USE_DEFAULT_WAIT,
&sa); // security attributes
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hEvents[1];
ResetEvent( hEvents[1] );
// wait for a connection...
bool bError = false;
bConnected = ConnectNamedPipe(hPipe, pOS);
if (!bConnected)
{
if (GetLastError() == ERROR_IO_PENDING)
{
// Wait for the data to be ready
DWORD dwWait = WaitForMultipleObjects( 2, hEvents, FALSE,
INFINITE );
if ( dwWait != WAIT_OBJECT_0+1 )
break; // Server stop or error
}
else
bError=true;
}
if (!bError)
{
//Create a thread to handle the request
CloseHandle(pOS->hEvent);
free(pOS);
}
}
SERVER WORKER THREAD:
----------------------
// create a Overlapped structure for read
OVERLAPPED *pOS = NULL;
HANDLE hOS = INVALID_HANDLE_VALUE;
// init the overlapped structure
hOS = CreateEvent(NULL,TRUE,FALSE,NULL);
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hOS;
ResetEvent( hOS );
// Get the size of the message
PeekNamedPipe(hPipe,NULL,0,NULL,&dwTotalBytesAvail,&dwBytesLeftInMessage);
// create a buffer based on the size from peek
bResult = ReadFile( hPipe,szBuffer,dwTotalBytesAvail,&dwBytesRead,pOS);
if ( !bResult )
{
if (ERROR_IO_PENDING == GetLastError())
{
DWORD dwNumBytesTransferred = 0;
// The data is not ready yet, wait for the operation to be
complete
GetOverlappedResult(hPipe,pOS, &dwNumBytesTransferred,true);
ResetEvent(pOS->hEvent);
}
}
CloseHandle(pOS->hEvent);
free(pOS);
pOS=NULL;
// Do stuff with the message and create a response
// create a Overlapped structure for write
*pOS = NULL;
hOS = INVALID_HANDLE_VALUE;
// init the overlapped structure
hOS = CreateEvent(NULL,TRUE,FALSE,NULL);
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hOS;
ResetEvent( hOS );
// Send the response
bResult = WriteFile( this->hPipe,
szOutMsg,
iOutMsgSize,
&dwBytesWritten,
pOverlapped);
if (!bResult)
{
int iWriteFileError = GetLastError();
if (ERROR_IO_PENDING == iWriteFileError)
{
DWORD dwNumBytesTransferred = 0;
// The data is not ready yet, wait for the operation to be
complete
GetOverlappedResult(hPipe,pOverlapped,&dwNumBytesTransferred,true);
ResetEvent(pOS->hEvent);
bResult = true;
}
}
CloseHandle(pOS->hEvent);
free(pOS);
pOS=NULL;
// Clean up
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle( hPipe );
----------------------
CLIENT THREAD:
DWORD dwPipeMode = PIPE_READMODE_MESSAGE;
hPipe = CreateFile( szPipeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if (hPipe == INVALID_HANDLE_VALUE)
WaitNamedPipe(szPipeName, 20000); // Then try again (not
shown here)
SetNamedPipeHandleState( this->hPipe, &dwPipeMode,NULL, NULL );
// Write the message
bResult = WriteFile( this->hPipe,
szOutMsg,
iOutMsgSize,
&dwBytesWritten,
NULL);
// Read the answer
bResult = PeekNamedPipe
(hPipe,NULL,0,NULL,&dwTotalBytesAvail,&dwBytesLeftInMessage);
if (dwTotalBytesAvail == 0)
{
// We don't know how big to make the buffer so default to 120
// since that is bigger than twice the size of
// most messages in testing.
dwTotalBytesAvail = 120;
}
ReadFile( hPipe, // file to read from
szBuffer, // address of input
buffer
dwTotalBytesAvail, // number of bytes to read
&dwBytesRead, // number of bytes read
NULL); // not overlapped
CloseHandle( hPipe );
named pipes. There is one multithreaded server that handles all of the
requests and multiple multithread clients that make the requests. The
problem is that the client hangs at the WriteFile request when running
under load. All the processes are running on the same box. I am
wondering if there is something I am doing wrong fundamentally.
One thing I am doing that is questionable is opening the pipe on the
server side in Overlapped mode and but not using overlapped mode on the
client side. I don't know if this would cause any problems since they
are on the same box.
If I change the server to open the pipe with a inital pipebuffer of 120
for read and write buffers the client then hangs at the readfile().
Any ideas?
SERVER MAIN:
----------------------
HANDLE hPipe = INVALID_HANDLE_VALUE;
HANDLE hEvents[2] = {NULL, NULL};
HANDLE hServerStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
hEvents[0] = hServerStopEvent;
while (1)
{
OVERLAPPED *pOS = NULL;
hEvents[1] = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
NULL); // no name
// Create the pipe
hPipe = CreateNamedPipe(
szPipeName,
PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
NMPWAIT_USE_DEFAULT_WAIT,
&sa); // security attributes
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hEvents[1];
ResetEvent( hEvents[1] );
// wait for a connection...
bool bError = false;
bConnected = ConnectNamedPipe(hPipe, pOS);
if (!bConnected)
{
if (GetLastError() == ERROR_IO_PENDING)
{
// Wait for the data to be ready
DWORD dwWait = WaitForMultipleObjects( 2, hEvents, FALSE,
INFINITE );
if ( dwWait != WAIT_OBJECT_0+1 )
break; // Server stop or error
}
else
bError=true;
}
if (!bError)
{
//Create a thread to handle the request
CloseHandle(pOS->hEvent);
free(pOS);
}
}
SERVER WORKER THREAD:
----------------------
// create a Overlapped structure for read
OVERLAPPED *pOS = NULL;
HANDLE hOS = INVALID_HANDLE_VALUE;
// init the overlapped structure
hOS = CreateEvent(NULL,TRUE,FALSE,NULL);
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hOS;
ResetEvent( hOS );
// Get the size of the message
PeekNamedPipe(hPipe,NULL,0,NULL,&dwTotalBytesAvail,&dwBytesLeftInMessage);
// create a buffer based on the size from peek
bResult = ReadFile( hPipe,szBuffer,dwTotalBytesAvail,&dwBytesRead,pOS);
if ( !bResult )
{
if (ERROR_IO_PENDING == GetLastError())
{
DWORD dwNumBytesTransferred = 0;
// The data is not ready yet, wait for the operation to be
complete
GetOverlappedResult(hPipe,pOS, &dwNumBytesTransferred,true);
ResetEvent(pOS->hEvent);
}
}
CloseHandle(pOS->hEvent);
free(pOS);
pOS=NULL;
// Do stuff with the message and create a response
// create a Overlapped structure for write
*pOS = NULL;
hOS = INVALID_HANDLE_VALUE;
// init the overlapped structure
hOS = CreateEvent(NULL,TRUE,FALSE,NULL);
pOS = (OVERLAPPED *) calloc (1, sizeof(OVERLAPPED) );
pOS->hEvent = hOS;
ResetEvent( hOS );
// Send the response
bResult = WriteFile( this->hPipe,
szOutMsg,
iOutMsgSize,
&dwBytesWritten,
pOverlapped);
if (!bResult)
{
int iWriteFileError = GetLastError();
if (ERROR_IO_PENDING == iWriteFileError)
{
DWORD dwNumBytesTransferred = 0;
// The data is not ready yet, wait for the operation to be
complete
GetOverlappedResult(hPipe,pOverlapped,&dwNumBytesTransferred,true);
ResetEvent(pOS->hEvent);
bResult = true;
}
}
CloseHandle(pOS->hEvent);
free(pOS);
pOS=NULL;
// Clean up
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle( hPipe );
----------------------
CLIENT THREAD:
DWORD dwPipeMode = PIPE_READMODE_MESSAGE;
hPipe = CreateFile( szPipeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if (hPipe == INVALID_HANDLE_VALUE)
WaitNamedPipe(szPipeName, 20000); // Then try again (not
shown here)
SetNamedPipeHandleState( this->hPipe, &dwPipeMode,NULL, NULL );
// Write the message
bResult = WriteFile( this->hPipe,
szOutMsg,
iOutMsgSize,
&dwBytesWritten,
NULL);
// Read the answer
bResult = PeekNamedPipe
(hPipe,NULL,0,NULL,&dwTotalBytesAvail,&dwBytesLeftInMessage);
if (dwTotalBytesAvail == 0)
{
// We don't know how big to make the buffer so default to 120
// since that is bigger than twice the size of
// most messages in testing.
dwTotalBytesAvail = 120;
}
ReadFile( hPipe, // file to read from
szBuffer, // address of input
buffer
dwTotalBytesAvail, // number of bytes to read
&dwBytesRead, // number of bytes read
NULL); // not overlapped
CloseHandle( hPipe );