Click here to Skip to main content
15,881,092 members
Articles / Programming Languages / C++
Article

IPCWorkshop

Rate me:
Please Sign up or sign in to vote.
4.91/5 (43 votes)
29 Jan 20037 min read 156.5K   4.5K   93   29
This article describes a data transfer over various IPC mechansisms

IPC Server

IPC Client

Introduction

The main objective of this application was to learn about the various Inter Process Communication methods and how it can be used for data transfer. This application also helps us to decide which of the available IPC methods is best to use. For a description of these IPC mechanisms I have taken a structure pointer named EmployeeData whose pointer is passed from the client to the server. For simplicity this demo application describes one way inter-process communication (ie) from the client to the server. The server will just listen to its clients. Here I have described 5 types of IPCs.

1 Clipboard Local Mc
2 File Mapping Local Mc
3 Mailslots Local Mc\Intranet
4 Named Pipes Local Mc\Intranet
5 Sockets Local Mc\Intranet\Internet

For detailed Information about the Inter Process Communication, you should read MSDN Library\Platform SDK Documentation\Base Services\InterProcess Communications

Clipboard

The clipboard is a set of functions and messages that enable applications to transfer data. Because all applications have access to the clipboard, data can be easily transferred between applications or within an application.

To Write in the Clipboard

  1. OpenClipboard
  2. Register Clipboard Format (Optional)
  3. Use global allocation for the data
  4. SetClipboardData
  5. CloseClipboard.

To Read from the Clipbaord

  1. OpenClipboard
  2. Register Clipboard Format (Optional)
  3. Check the clipboard format is available
  4. Get the clipboard data
  5. Unlock the handle

SDK functions are available for the above operations. CClipboard is a class that provides developers with a simple way to implement the clipboard functions. Write the data in the clipboard as easy as shown below.

CClipboard m_objClipboard;
m_objClipboard.Open();
m_objClipboard.Write( (char*)data, size );
Read the data from the clipboard as shown below.
CClipboard m_objClipboard;
m_objClipboard.Open();
m_objClipboard.Read( data, size);

Many standard clipboard formats are available. If you want to support more applications to work on the clipboard at the same time, then register a new clipboard format. (Optional)

m_objClipboard.Register("New format") // any name
In this demo application, the client notifies the server by posting message with handle HWND_BROADCAST.

File Mapping

File mapping is an efficient way for two or more processes on the same computer to share data. Here i have not described about the synchronization of the process. In order to access the file's contents, the processes uses virtual address space called file view. Processes read from and write to the file view using pointers, just as they would with dynamically allocated memory.

To write in the file

  1. Create File Mapping
  2. map the handle to the process virtual address space (MapViewOfFile)
  3. copy the data in the file

To Read from the File

  1. Create File Mapping
  2. maps the handle to the process virtual address space (MapViewOfFile)
  3. copy the data from the file.
CFileMapping is a class which encapsulates the file mapping functions provided by the SDK. Using the above class sharing the data between two or more processes can be easily done. Write the data in the shared file as shown below.
CFileMapping m_objFilemapping;
m_objFilemapping.Initialize( "ANY FILE NAME", size/* size of the filemap*/);
m_objFilemapping.Write( (char*) data);

If the name of the filemap is known then we can read the data from any other process as shown below.

CFileMapping m_objFilemapping;
m_objFilemapping.Initialize( "ANY FILE NAME", size);
m_objFilemapping.Read( data );

Notify the server using HWND_BROADCAST handle. we have successfully transferred the pointer between two processes on the same local machine. we get curious of how to pass this pointer in the Intranet if this two processes resides on different computers. Next section is Named Pipes and Mailslots.

Mailslots

Any win32 application can store messages in a mailslot and the owner will retrieve messages that are stored there. Mailslot is a simple way for a process to broadcast messages to multiple processes using datagram. Hence there won't be any confirmation of the receipt. This is a mechanism for one way inter process communication.

To write in the Mailslot

  1. Create a Mailslot (CreateMailslot)
  2. Write data in the mailslot (WriteFile)

To Read from the Mailslot

  1. Open the mailslot (CreateFile)
  2. check for the messages in the mail slot (GetMailslotInfo)
  3. Read data from the Mailslot (ReadFile)
CMailslot is a class that can be used to create both mail slot server as well as mail slot client.
Mailslot Server Mailslot Client
CMailslot m_objMailslot; CMailslot m_objMailslot;
m_objMailslot.Initialize( <br>
          true /*IsServer*/,<br> 
          "Any Mailslot Name");
m_objMailslot.Initialize(<br>
         false /*IsServer*/,<br>      "Any Mailslot Name");
m_objMailslot.Listen(messageId, lparam);  
  m_objMailslot.Write(data)
fired to messageId  
m_objMailslot.Read(data);  

Internal Details :- A mailslot server is a process that creates and owns a mailslot. When the server creates a mailslot it receives a mailslot handle.

m_strMailslot.Format("\\\\.\\mailslot\\%s", pMailslotName);
m_hInputslot = CreateMailslot(  m_strMailslot,    // mailslot name
                                0,                // message can be of any size
                                MAILSLOT_WAIT_FOREVER, // waits forever for a message
                                NULL             // It cannot be inherited
                             );

The mailslot server can read messages in the mailslot at any time. For the automatic response of the server you can use Listen(messageId, lparam). Here the messageId is the RegisterWindowMessage identity. In the listen function, a worker thread is created to continuously check for messages in the mailslot. If any messages found, it fires to the messageId for the read operation. The total messages will be reduced only at the end of read operation. Hence in this function SendMessageTimeOut is used in order to decrement the message count. Let us check the total messages in the mailslot.

while(1) {
         GetMailslotInfo( This->GetInputslot(), NULL, &message, 
                          &noofMessages, NULL ); 
         if( noofMessages > 0) {
           // The total messages will be reduced only at the end of read operation
           // Hence don't use post message operation.
           LRESULT returnVal = ::SendMessageTimeout(HWND_BROADCAST, 
                                       This->GetTransferMessage(),
                                       NULL, This->GetLparam(), SMTO_BLOCK,
                                       MESSAGETIMEOUT, NULL);
           if( returnVal == 0)
                TRACE("Unable to send message. Error is %d", 
                             GetLastError());
         }
}

Read the mailslot message using the created mailslot handle.

while( noofMessages != 0) {
       ReadFile( m_hInputslot, buffer, size, &dataRead, NULL);
       GetMailslotInfo(  m_hInputslot,           // mailslot handle
                         0,                      // message can be of any size
                         &message,           // size of next message
                         &noofMessages,      // number of messages
                         NULL                    // read time-out interval
                      );
}

A mailslot client is a process that writes a message to a mailslot. Any process that has the name of a mailslot can put a message there. New messages follow any existing messages in the mailslot. The client opens the mailslot using CreateFile.

m_strMailslot.Format("\\\\*\\mailslot\\%s", pMailslotName);
m_hOutputslot = CreateFile(  m_strMailslot,          // file name
                             GENERIC_WRITE,          // Only Write Permission
                             0,                      // cannot be shared
                             NULL,                   // SD
                             OPEN_EXISTING,          // Opens the file. fails if 
                                                     // file doesn't exist
                             FILE_ATTRIBUTE_NORMAL,  // file attributes
                             NULL                    // handle to template file
                          );

Write the data in the mailslot is as simple as shown below.

DWORD sizeWritten;
WriteFile( m_hOutputslot, pData, m_nSize, &sizeWritten, NULL);
if( sizeWritten == 0 )
    TRACE(" Unable to write to the Mail slot. Error is %d", 
          GetLastError() );

NAMEDPIPES

A named pipe is a named, one-way or duplex pipe for communication between the pipe server and one or more pipe clients. Named pipes are like telephone calls: you talk only to one party, but you know that the message is being received.

To Write in the pipe.

  1. Create a named pipe. (with or without security attributes)
  2. Write the data in the file. (at the time of writing the server should listen)

To read from the pipe

  1. Open the named pipe.
  2. Continuously read from the pipe
  3. Notify that the message has been received.
CNamedPipe is a simple class used to support named pipe operations.

 

Named Pipe Server Named Pipe Client
CNamedPipe m_objNamedPipe; CNamedPipe m_objNamedPipe;
m_objNamedPipe.Initialize( <br>
          true /*IsServer*/,<br>      
    "." /*Server name*/, <br>      "Any NamedPipe Name");
m_objNamedPipe.Initialize( <br>
       false /*IsServer*/,<br>      "server" /*Server name*/,<br>     
  "Any NamedPipe Name");
m_objNamedPipe.Listen(messageId, lparam);  
  m_objNamedPipe.Write(data)
fired to messageId  
m_objNamedPipe.Read(data);  
 

Call the Initialize function of the CNamedPipe to create named pipe server and named pipe client. A named pipe server, refers to a process that creates a named pipe.

m_strPipeName.Format("\\\\.\\pipe\\%s", pPipeName);
m_hInputPipeHandle = CreateNamedPipe(
                       m_strPipeName,          // pipe name
                       PIPE_ACCESS_INBOUND,    // client to the server
                       PIPE_WAIT,              // Blocking mode is enabled
                       1,                      // support given to only one client
                       0,                      // output buffer size
                       0,                      // input buffer size
                       PIPE_TIMEOUT,           // time-out interval
                       NULL                    // Security Attributes
                                    );

If the security attribute is NULL, then the transfer of data will be available to only Local machine. Inorder to support across the network, set the security attribute.

SECURITY_ATTRIBUTES saPipe;
saPipe.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) malloc
                                              (SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(saPipe.lpSecurityDescriptor,
                             SECURITY_DESCRIPTOR_REVISION);
// Access Control list is asiigned as NULL inorder to allow all access to 
// the object.
SetSecurityDescriptorDacl(saPipe.lpSecurityDescriptor, TRUE, (PACL) NULL,FALSE);
saPipe.nLength = sizeof(saPipe);
saPipe.bInheritHandle = TRUE; 

This created pipe will listen continuously for the client to write data. Inorder to satisfy this condition a worker thread is created. In the mailslot the infinite thread is an optional, we can give an external control to read from the mailslot. Since the pipe is created in the blocking mode, this infinite thread is necessary. Otherwise the client will get hanged while writing data. This thread named as Listenerproc will continuously read the file. If the data is read then it will notify to the messageId.

UINT ListenerProc( LPVOID pNamedPipe )
{
    CNamedPipe* This = (CNamedPipe*)pNamedPipe;
    if( This == NULL )
        return 0;
    int size = This->GetSize();

    // assign the size of the data to be read.
    ASSERT( size != 0 );
    ASSERT( This->GetTransferMessage() != NULL);
    char* buff = new char[size];
    DWORD dataRead;
    while(1) {
        BOOL isRead = ReadFile( This->GetInputPipeHandle(), 
                                          buff, size, &dataRead, NULL);
        if( dataRead > 0) {
            // acts as a post thread message
            // since this is internal to the process, it can also 
            // work on the network satisfying the named pipe advantage.
            ::PostMessage( HWND_BROADCAST, 
                This->GetTransferMessage(), (WPARAM)buff, This->GetLparam());
        }        
    }
    return 1;
}

A named pipe client, opens the named pipe handle using CreateFile. With the help of the handle the client writes the data to the server. This procedure is same as in the mailslot. please refer above.

Sockets

A socket is a communication endpoint - an object through which a Windows Sockets application sends or receives packets of data across a network.Here I have used a only a bit of portion for data transfer from the huge topic Window Sockets. This application uses stream socket. MFC class CSocket provides encapsulation of the windows socket API.

 

Server Socket Client Socket
Construct a socket Construct a socket
Create the socket Create the socket
Start listening  
  <--- Connect
Accept the client  
  <--- Send Data
Receive data.  

CDerivedSocket is a class derived from the MFC class CSocket. This class only describes the data transfer from the client to the server.

History

Version 1.0

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
Iam a software developer from Chennai, India. I've been working mainly under windows environment.I am attracted to various programming languages including : C/C++, Python. I've been programming VC++/MFC, ATL/COM, Lex & Yacc and database design/development ( SQL/Oracle ) for the past two years.



Comments and Discussions

 
GeneralRe: Another option... WM_COPYDATA Pin
Venkat Raman24-Jan-03 17:37
Venkat Raman24-Jan-03 17:37 
GeneralCool Pin
Ernest Laurentin22-Jan-03 6:12
Ernest Laurentin22-Jan-03 6:12 
GeneralRe: Cool Pin
Venkat Raman24-Jan-03 17:34
Venkat Raman24-Jan-03 17:34 
GeneralRe: Cool Pin
cowboy00722-Sep-04 17:53
cowboy00722-Sep-04 17:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.