Pages

Monday, January 13, 2014

Inter Process Communication: Windows NamedPipes & Java Applications

A Named Pipe is a mechanism for communication between processes. One process has to create the Named Pipe (termed as pipe server) and one or more processes can connect to this Named Pipe (pipe clients) using the unique name given to it, when it was created. 


A Named Pipe can be used for both uni directional as well as bidirectional data transfer between the server and client, once a connection is established. This simple example demonstrates the basics of creating and managing a Named Pipe using WIN32 APIs, connecting to it through a client program (Java application) and performing bidirectional data communication.

WIN32 Application (Pipe Server)


#include "stdafx.h"
#include "windows.h"

int _tmain(int argc, _TCHAR* argv[])
{
    do
    {
        DWORD error = 0; //Window error code.
        DWORD bytesRead = 0; //Number of bytes read from pipe.
        DWORD bytesWritten = 0; //Number of byets written to pipe.
        BYTE pipeData = 0x00; //Data read from pipe
        BOOL result = FALSE; //Pipe activity result
        const TCHAR * pipeName = _T("\\\\.\\pipe\\MyWindowsNamedPipe");
 
        //Create Named Pipe with given name.
        HANDLE hPipe = CreateNamedPipe(pipeName, 
                                PIPE_ACCESS_DUPLEX,
                                0,
                                (PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT),
                                PIPE_UNLIMITED_INSTANCES,
                                512,
                                0,
                                NULL);
 
        if (hPipe == INVALID_HANDLE_VALUE)
        {
            _tprintf(_T("Create named pipe with name %s failed. Error Code %08X.\n"), pipeName, GetLastError());
            break;
        }

        //Wait for client to connect.
        _tprintf(_T("Waiting for client connection...\n"), GetLastError());
        result = ConnectNamedPipe(hPipe, NULL);
        if (result == FALSE)
        {
            _tprintf(_T("Wait for client connection failed. Error Code %08X.\n"), GetLastError());
            break;
        }
        else
        {
            _tprintf(_T("Client connected.\n"), GetLastError());
        }
 
        while (true)
        {
            bytesRead = 0;
            result = ReadFile(hPipe, &pipeData, 1, &bytesRead, NULL);
            if (bytesRead == 1)
            {
                if (pipeData == 0xFF)
                {
                    _tprintf(_T("Exit command received.\n"));
                     break;
                }
                else
                {
                    //Echo data
                    WriteFile(hPipe, &pipeData, 1, &bytesWritten, NULL);
                   if (bytesWritten == 0)
                   {
                       _tprintf(_T("Write to pipe failed. Error Code %08X.\n"), GetLastError());
                       break;
                   }
                }
            }
            else
            {
                _tprintf(_T("Read from pipe failed. Error Code %08X.\n"), GetLastError());
                break;
            }
        }

        CloseHandle(hPipe);
    } while (false);

    //Wait for user input to terminate.
    system("PAUSE");
    return 0;
}


Java Application (Pipe Client)


package com.scratchnote.NamedPipe;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class NamedPipeClient {
 
    public static void main(String[] args) {
        try {
            //Pipe name should be identical to the name used by server.
            final String pipeName = "\\\\.\\pipe\\MyWindowsNamedPipe";
   
            //Data to be transmitted over pipe.
            final String pipeData = "Hello Pipe";
   
            final byte[] pipeDataBytes = pipeData.getBytes();
   
            //Open pipe with read / write access.
            RandomAccessFile pipe = new RandomAccessFile(pipeName, "rw");
   
            try {
                for (int i = 0; i < pipeData.length(); i++) {
                    System.out.println("Writing data byte 0x" + 
                                        Integer.toHexString(pipeDataBytes[i]) + 
                                        " (" + ((char)pipeDataBytes[i]) + ") " +
                                        "to pipe...");
                    pipe.write(pipeDataBytes[i]);
                    do {
                        int rxData = pipe.read();
                        System.out.println("Byte read from pipe: 0x" + 
                                           Integer.toHexString(rxData) +
                                           " (" + ((char)rxData) + ")");
                    } while (pipe.length() > 0);
                    System.out.println();
                }
    
                //Send exit command.
                pipe.write(0xFF);
            } catch (IOException e) {
                e.printStackTrace();
            }
      
            //Close pipe connection.
            pipe.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

No comments:

Post a Comment