vendredi 6 novembre 2020

What's the order of use of Win32 APIs for Server-client Pipe comm. in C++ (CreateNamedPipe, WriteFile, CreateFile, ReadFile)

I am trying out to write a server-client program in C++, in Visual Studio 2019, using WIN32 APIs. This is the referred documentation: https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-open-modes

I have used 4 APIs: On the server side (the one creating the pipe and writing to it): CreateNamedPipe(), WriteFile() On the client side (the one connecting and reading from the pipe): CreateFile(), ReadFile()

However, for a reason, I observe, the server is NOT able to write to the pipe. Following is the code I have used.

Servermain.cpp

#include <iostream>
#include <windows.h>

using namespace std;

void namedPipeServer()
{
    HANDLE hPipeServer;
    char Wbuffer[1024] = "Hello, from the pipe server!";
    DWORD dwWrite;
    BOOL writeSuccessFlag;

    //Create a named pipe
    hPipeServer = CreateNamedPipe(
        TEXT("\\\\.\\pipe\\Agentpipe"), //lpName
        PIPE_ACCESS_OUTBOUND,        //dwOpenMode
        PIPE_TYPE_BYTE,            //dwPipeMode
        1,                         //nMaxInstances
        1024 * 16,                 //nOutBufferSize
        1024 * 16,                 //nInBufferSize
        NMPWAIT_USE_DEFAULT_WAIT,  //nDefaultTimeOut
        NULL);                     //lpSecurityAttributes

    cout << "Inside namedPipeServer()" << endl;

    if (hPipeServer != INVALID_HANDLE_VALUE)
    {
        cout << "Just writing to pipe" << endl;

        writeSuccessFlag = WriteFile(
            hPipeServer, //HANDLE       hFile
            Wbuffer,     //LPCVOID      lpBuffer
            30,          //DWORD        nNumberOfBytesToWrite
            &dwWrite,
            NULL         //LPOVERLAPPED lpOverlapped
        );

        if (writeSuccessFlag)
        {
            cout << "Server has written to pipe!" << endl;
        }
        else
        {
            cout << "Unsuccessful write to pipe, From Agent" << endl;
        }
    }
    else
    {
        cout << "Unsuccesful pipe connection. hPipeServer: " << hPipeServer << endl;
    }
}

int main()
{
    cout << "Inside Agent server. Creating a named pipe.\n" << endl;
    namedPipeServer();
    while (1);
    return 0;
}

Clientmain.cpp:

#include <iostream>
#include <windows.h>

using namespace std;

void readFromPipe()
{
    HANDLE hPipeClient;
    char rBuffer[1024];
    DWORD dwRead;
    BOOL readSuccessFlag = 0;

    //Connect to the server pipe: \\.\\pipe\\Agentpipe
    cout << "Inside readFromPipe()." << endl;

    hPipeClient = CreateFile(
        TEXT("\\\\.\\pipe\\Agentpipe"), //lpFileName
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL
    );

    while (hPipeClient != INVALID_HANDLE_VALUE)
    {
        cout << "Just connecting to pipe" << endl;
        readSuccessFlag = ReadFile(
            hPipeClient, //HANDLE       hFile,
            rBuffer,     //LPVOID       lpBuffer,
            30,          //DWORD        nNumberOfBytesToRead,
            &dwRead,     //LPDWORD      lpNumberOfBytesRead,
            NULL         //LPOVERLAPPED lpOverlapped
        );

        if (readSuccessFlag)
        {
            cout << "Client has read from pipe of Agent!" << endl;
            cout << "From Agent Pipe: " << rBuffer << endl;
        }
        else
        {
            cout << "Unsuccessful Pipe read!" << endl;
        }
    }
    if(hPipeClient == INVALID_HANDLE_VALUE)
    {
        cout << "Unsuccesful pipe connection at client end. hPipeClient: " << hPipeClient << endl;
    }
}

int main()
{
    cout << "Inside the client. Calling readFromPipe()" << endl;
    readFromPipe();
    while (1);
    return 0;
}

The above program when executed shows that the server is NOT able to the pipe, and the: Output on the server-side is:

Inside Agent server. Creating a named pipe. Inside namedPipeServer() Just writing to pipe Unsuccessful write to pipe, From Agent

Output on the client console is: Inside the client. Calling readFromPipe() Inside readFromPipe(). Just connecting to pipe

Upon looking into WIN32 documentation, sample program: I have observed that the order of use of these WIN32 APIs is different, that looks like the below: Pipe Server program:

main(){
    ...
    namedPipeServer()
    ...
}

void namedPipeServer()
{
     ...
      CreateFile()
      WriteFile()
     ...
}

Pipe Client program:

main(){
     ...
     readFromPipe()
     ...
}

void readFromPipe()
{
      ...
      CreateNamedPipe()
      ReadFile()
      ...
}

I would be happy if anyone can provide me with clarity on the use of CreateNamedPipe() & CreateFile() especially. Q1) Does the server have to use CreateFile() first (to create the pipe, before writing to it), or can I use CreateNamedPipe()? Q2) Is the order of use of the APIs in MY program posted incorrect? If it is, please specify why.

Aucun commentaire:

Enregistrer un commentaire