Google Answers Logo
View Question
 
Q: Small Named Pipe Question ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: Small Named Pipe Question
Category: Computers > Programming
Asked by: fikal-ga
List Price: $3.00
Posted: 19 Oct 2006 15:45 PDT
Expires: 18 Nov 2006 14:45 PST
Question ID: 775173
I have taken the source code for an example off microsoft.com for a
Named Pipe Server example.  However, I have modified it very slightly
to attempt to return variables back to the client instead of just
plain text.  I will also include the client code if you need that for
testing reasons.

the error lies in the VOID GetAnswerToRequest function.

SERVER CODE
----------------------------------------------------------------------
#include <windows.h> 
#include <stdio.h> 
#include <tchar.h>

#define BUFSIZE 4096
 
DWORD WINAPI InstanceThread(LPVOID); 
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD); 
 
int _tmain(VOID) 
{ 
   BOOL fConnected; 
   DWORD dwThreadId; 
   HANDLE hPipe, hThread; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
 
// The main loop creates an instance of the named pipe and 
// then waits for a client to connect to it. When the client 
// connects, a thread is created to handle communications 
// with that client, and the loop is repeated. 
 
   for (;;) 
   { 
      hPipe = CreateNamedPipe( 
          lpszPipename,             // pipe name 
          PIPE_ACCESS_DUPLEX,       // read/write access 
          PIPE_TYPE_MESSAGE |       // message type pipe 
          PIPE_READMODE_MESSAGE |   // message-read mode 
          PIPE_WAIT,                // blocking mode 
          PIPE_UNLIMITED_INSTANCES, // max. instances  
          BUFSIZE,                  // output buffer size 
          BUFSIZE,                  // input buffer size 
          NMPWAIT_USE_DEFAULT_WAIT, // client time-out 
          NULL);                    // default security attribute 

      if (hPipe == INVALID_HANDLE_VALUE) 
      {
          printf("CreatePipe failed"); 
          return 0;
      }
 
      // Wait for the client to connect; if it succeeds, 
      // the function returns a nonzero value. If the function
      // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. 
 
      fConnected = ConnectNamedPipe(hPipe, NULL) ? 
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
 
      if (fConnected) 
      { 
      // Create a thread for this client. 
         hThread = CreateThread( 
            NULL,              // no security attribute 
            0,                 // default stack size 
            InstanceThread,    // thread proc
            (LPVOID) hPipe,    // thread parameter 
            0,                 // not suspended 
            &dwThreadId);      // returns thread ID 

         if (hThread == NULL) 
         {
            printf("CreateThread failed"); 
            return 0;
         }
         else CloseHandle(hThread); 
       } 
      else 
        // The client could not connect, so close the pipe. 
         CloseHandle(hPipe); 
   } 
   return 1; 
} 
 
DWORD WINAPI InstanceThread(LPVOID lpvParam) 
{ 
   TCHAR chRequest[BUFSIZE]; 
   TCHAR chReply[BUFSIZE]; 
   DWORD cbBytesRead, cbReplyBytes, cbWritten; 
   BOOL fSuccess; 
   HANDLE hPipe; 
 
// The thread's parameter is a handle to a pipe instance. 
 
   hPipe = (HANDLE) lpvParam; 
 
   while (1) 
   { 
   // Read client requests from the pipe. 
      fSuccess = ReadFile( 
         hPipe,        // handle to pipe 
         chRequest,    // buffer to receive data 
         BUFSIZE*sizeof(TCHAR), // size of buffer 
         &cbBytesRead, // number of bytes read 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbBytesRead == 0) 
         break; 
      GetAnswerToRequest(chRequest, chReply, &cbReplyBytes); 
 
   // Write the reply to the pipe. 
      fSuccess = WriteFile( 
         hPipe,        // handle to pipe 
         chReply,      // buffer to write from 
         cbReplyBytes, // number of bytes to write 
         &cbWritten,   // number of bytes written 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbReplyBytes != cbWritten) break; 
  } 
 
// Flush the pipe to allow the client to read the pipe's contents 
// before disconnecting. Then disconnect the pipe, and close the 
// handle to this pipe instance. 
 
   FlushFileBuffers(hPipe); 
   DisconnectNamedPipe(hPipe); 
   CloseHandle(hPipe); 

   return 1;
}

VOID GetAnswerToRequest(LPTSTR chRequest, 
   LPTSTR chReply, LPDWORD pchBytes)
{
   lstrcpy( chReply, _tprintf( TEXT("Welcome to the server, %s\n"), chRequest) );
   
   *pchBytes = (lstrlen(chReply)+1)*sizeof(TCHAR);
}
--------------------------------------------------------------
CLIENT CODE
--------------------------------------------------------------
#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream.h>

#define BUFSIZE 512
#define MAXSIZE 15 

int _tmain(int argc, TCHAR *argv[]) 
{ 
   HANDLE hPipe; 
   LPTSTR lpvMessage=TEXT("Default message from client"); 
   TCHAR chBuf[BUFSIZE]; 
   BOOL fSuccess; 
   DWORD cbRead, cbWritten, dwMode; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
   
   char name[MAXSIZE];  // name for sending to server 


   if( argc > 1 )
      lpvMessage = argv[1];
 
// 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) 
      {
         printf("Could not open pipe"); 
         return 0;
      }
 
      // All pipe instances are busy, so wait for 20 seconds. 
 
      if (!WaitNamedPipe(lpszPipename, 20000)) 
      { 
         printf("Could not open pipe"); 
         return 0;
      } 
   } 
 
// 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) 
   {
      printf("SetNamedPipeHandleState failed"); 
      return 0;
   }
 
// Send a message to the pipe server. 
 
   //Send player name to the server
   cout << "Enter Player name : " << endl;
   cin >> name;
   
   fSuccess = WriteFile( 
      hPipe,                  // pipe handle 
      name,					  // message 
      (lstrlen(name)+1)*sizeof(TCHAR), // message length 
      &cbWritten,             // bytes written 
      NULL);                  // not overlapped 
   if (!fSuccess) 
   {
      printf("WriteFile failed"); 
      return 0;
   }
 
   do 
   { 
   // 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);    // not overlapped 
 
      if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
         break; 
 
      _tprintf( TEXT("%s\n"), chBuf ); 
   } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA 

   getch();
 
   CloseHandle(hPipe); 
 
   return 0; 
}

Request for Question Clarification by efn-ga on 19 Oct 2006 20:58 PDT
What is the question?  What is the error?

Clarification of Question by fikal-ga on 20 Oct 2006 11:39 PDT
c:\cpp2.cpp(125) : error C2664: 'lstrcpyA' : cannot convert parameter
2 from 'int' to 'const char *'
        Conversion from integral type to pointer type requires
reinterpret_cast, C-style cast or function-style cast

i would just like this to be able to run error free :)
Answer  
Subject: Re: Small Named Pipe Question
Answered By: theta-ga on 20 Oct 2006 15:37 PDT
Rated:5 out of 5 stars
 
Hi fikal-ga,
  The error you are experiencing occurs due to the following line in
the GetAnswerToRequest() method of the server code:
   lstrcpy( chReply, _tprintf( TEXT("Welcome to the server, %s\n"), chRequest) );
   The problem here is that the lstrcpy() method expects two tchars as
its arguments. However, you have provided the _tprintf() as the second
argument, and _tprintf() just returns an integer denoting the number
of charcters printed on the screen. Hence the error.
   What you are trying to do is create a string containing the text
"Welcome to the server," followed by the string value sent by the
client. To concatenate the two values, you need to use the _stprintf()
method, not _tprintf().
  So instead of having the lstrcpy() call, replace that line with:
     _stprintf(chReply, TEXT("Welcome to the server, %s\n"), chRequest);
and now the server will compile without any errors! 
  The _stprintf() method is just a wrapper for sprintf()/swprintf()
functions. For more details on them, see:
   - MSDN: sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l
     [http://msdn2.microsoft.com/en-us/library/ybk95axf.aspx]

   I also encountered a bunch of errors while compiling the client
code. All these errors were due to the fact that the use of TCHARS and
plain chars had been mixed up in the code. The name variable had been
declared as char[] instead of TCHAR[]. This made the lstrlen(name)
call in WriteFile() complain. So I fixed the declaration and made name
a TCHAR[]. The next part was the use of cin and cout in the code.
There is by default no equivalent of cin and cout provided for use
with TCHARs. So I replaced them with _tprintf() and _tscanf(). I also
removed the iostream include declaration since it was no longer in
use.
  You can download the updated source files from
[http://rapidshare.com/files/71370/namedpipes.zip.html]
  I am also including the modified code3 below:
========================= SERVER =============================
#include <windows.h> 
#include <stdio.h> 
#include <tchar.h>

#define BUFSIZE 4096
 
DWORD WINAPI InstanceThread(LPVOID); 
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD); 
 
int _tmain(VOID) 
{ 
   BOOL fConnected; 
   DWORD dwThreadId; 
   HANDLE hPipe, hThread; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
 
// The main loop creates an instance of the named pipe and 
// then waits for a client to connect to it. When the client 
// connects, a thread is created to handle communications 
// with that client, and the loop is repeated. 
 
   for (;;) 
   { 
      hPipe = CreateNamedPipe( 
          lpszPipename,             // pipe name 
          PIPE_ACCESS_DUPLEX,       // read/write access 
          PIPE_TYPE_MESSAGE |       // message type pipe 
          PIPE_READMODE_MESSAGE |   // message-read mode 
          PIPE_WAIT,                // blocking mode 
          PIPE_UNLIMITED_INSTANCES, // max. instances  
          BUFSIZE,                  // output buffer size 
          BUFSIZE,                  // input buffer size 
          NMPWAIT_USE_DEFAULT_WAIT, // client time-out 
          NULL);                    // default security attribute 

      if (hPipe == INVALID_HANDLE_VALUE) 
      {
          printf("CreatePipe failed"); 
          return 0;
      }
 
      // Wait for the client to connect; if it succeeds, 
      // the function returns a nonzero value. If the function
      // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. 
 
      fConnected = ConnectNamedPipe(hPipe, NULL) ? 
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
 
      if (fConnected) 
      { 
      // Create a thread for this client. 
         hThread = CreateThread( 
            NULL,              // no security attribute 
            0,                 // default stack size 
            InstanceThread,    // thread proc
            (LPVOID) hPipe,    // thread parameter 
            0,                 // not suspended 
            &dwThreadId);      // returns thread ID 

         if (hThread == NULL) 
         {
            printf("CreateThread failed"); 
            return 0;
         }
         else CloseHandle(hThread); 
       } 
      else 
        // The client could not connect, so close the pipe. 
         CloseHandle(hPipe); 
   } 
   return 1; 
} 
 
DWORD WINAPI InstanceThread(LPVOID lpvParam) 
{ 
   TCHAR chRequest[BUFSIZE]; 
   TCHAR chReply[BUFSIZE]; 
   DWORD cbBytesRead, cbReplyBytes, cbWritten; 
   BOOL fSuccess; 
   HANDLE hPipe; 
 
// The thread's parameter is a handle to a pipe instance. 
 
   hPipe = (HANDLE) lpvParam; 
 
   while (1) 
   { 
   // Read client requests from the pipe. 
      fSuccess = ReadFile( 
         hPipe,        // handle to pipe 
         chRequest,    // buffer to receive data 
         BUFSIZE*sizeof(TCHAR), // size of buffer 
         &cbBytesRead, // number of bytes read 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbBytesRead == 0) 
         break; 
      GetAnswerToRequest(chRequest, chReply, &cbReplyBytes); 
 
   // Write the reply to the pipe. 
      fSuccess = WriteFile( 
         hPipe,        // handle to pipe 
         chReply,      // buffer to write from 
         cbReplyBytes, // number of bytes to write 
         &cbWritten,   // number of bytes written 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbReplyBytes != cbWritten) break; 
  } 
 
// Flush the pipe to allow the client to read the pipe's contents 
// before disconnecting. Then disconnect the pipe, and close the 
// handle to this pipe instance. 
 
   FlushFileBuffers(hPipe); 
   DisconnectNamedPipe(hPipe); 
   CloseHandle(hPipe); 

   return 1;
}

VOID GetAnswerToRequest(LPTSTR chRequest, 
   LPTSTR chReply, LPDWORD pchBytes)
{
   _tprintf( TEXT("Welcome to the server, %s\n"), chRequest) ;
   _stprintf(chReply, TEXT("Welcome to the server, %s\n"), chRequest);
   
   *pchBytes = (lstrlen(chReply)+1)*sizeof(TCHAR);
}
========================= SERVER =============================
========================= CLIENT =============================
#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUFSIZE 512
#define MAXSIZE 15 

int _tmain(int argc, TCHAR *argv[]) 
{ 
   HANDLE hPipe; 
   LPTSTR lpvMessage=TEXT("Default message from client"); 
   TCHAR chBuf[BUFSIZE]; 
   BOOL fSuccess; 
   DWORD cbRead, cbWritten, dwMode; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
   
   TCHAR name[MAXSIZE];  // name for sending to server 


   if( argc > 1 )
      lpvMessage = argv[1];
 
// 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) 
      {
         printf("Could not open pipe"); 
         return 0;
      }
 
      // All pipe instances are busy, so wait for 20 seconds. 
 
      if (!WaitNamedPipe(lpszPipename, 20000)) 
      { 
         printf("Could not open pipe"); 
         return 0;
      } 
   } 
 
// 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) 
   {
      printf("SetNamedPipeHandleState failed"); 
      return 0;
   }
 
// Send a message to the pipe server. 
 
   //Send player name to the server
   _tprintf(TEXT("%s\n"), TEXT("Enter Player name : "));
   _tscanf(TEXT("%s"), name);
   
   fSuccess = WriteFile( 
      hPipe,                  // pipe handle 
      name,					  // message 
      (lstrlen(name)+1)*sizeof(TCHAR), // message length 
      &cbWritten,             // bytes written 
      NULL);                  // not overlapped 
   if (!fSuccess) 
   {
      printf("WriteFile failed"); 
      return 0;
   }
 
   do 
   { 
   // 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);    // not overlapped 
 
      if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
         break; 
 
      _tprintf( TEXT("%s\n"), chBuf ); 
   } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA 

   getch();
 
   CloseHandle(hPipe); 
 
   return 0; 
}
========================= CLIENT =============================

If you intend to modify this code further, you might be interested in
the following links related to UNICODE aware programming under C++:

   - Unicode-enabling Microsoft C/C++ Source Code
     [http://www.i18nguy.com/unicode/c-unicode.html]

   - Unicode Tutorial
     [http://www.rohitab.com/discuss/lofiversion/index.php/t12509.html]

   - MSDN: Run Time Library Routine Mappings
     [http://msdn2.microsoft.com/en-us/library/tsbaswba.aspx]

=================================================================

Hope this helps!
If you need any clarifications, just ask!

Regards,
Theta-ga
:)
fikal-ga rated this answer:5 out of 5 stars and gave an additional tip of: $1.00
great answer, helped clarify some new concepts for me

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy