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
:) |