- ad Named Pipe Server source - 3.71 Kb
- Download Named Pipe Client source - 3.74 Kb
- Download Mailslot Server source - 3.47 Kb
- Download Mailslot Client source - 3.56 Kb
- WindowIPC.zip 내가 직접 수정한 파일
Introduction
There are many options available for Inter-Process Communication (IPC) on Windows. I will try to list them out, along with some of the advantages and disadvantages of using them. This article is pretty much a beginner’s article.
Definitions of IPC
I found some formal definitions of Inter-Process Communication, on the internet:
- Inter-Process Communication, which in short is known as IPC, deals mainly with the techniques and mechanisms that facilitate communication between processes.
- A capability supported by some operating systems that allows one process to communicate with another process. The processes can be running on the same computer, or on different computers connected through a network.
Background
The design of a product or project of decent size and complication requires that two or more processes communicate.
There are many options using which this communication can be accomplished. For example, if your processes are using message queues, then you can use the message WM_COPYDATA
to transfer data between the processes. The Windows Clipboard can also be used.
COM/DCOM/RPC technologies can be used for IPC. These technologies are out of the scope of this article.
A few other mechanisms that I will highlight in this article are:
- Shared Memory (memory mapped object).
- Named Pipe.
- WinSock.
- Mailslot.
It is important to know about Windows Synchronization objects when working with IPC. Almost every time some IPC mechanism is used, it is used along with some inter-process synchronization mechanism.
The following are the synchronization objects that can be used to synchronize between processes:
- Mutex
- Semaphore
- Events
There is one more synchronization object – Critical Section. However, a Critical Section is used for synchronization within the threads of a single process. It can’t be used for synchronization between processes. A detailed discussion of Windows Synchronization is out of the scope of this article.
Using the code
Shared Memory
Following are some of the Win32 APIs that are used when working with shared memory (memory mapped objects):
CreateFileMapping()
MapViewOfFile()
UnMapViewOfFile()
CloseHandle()
Notes on Shared Memory:
- Source code is platform dependent.
- Can only be used for processes that are on the same computer.
- Once a memory mapped object is mapped into the process area, using it is very straightforward and easy.
- Perhaps the fastest IPC mechanism.
The source code demonstrating the use of memory mapped objects can be found on my other article: Synchronization of multiple reader and writer processes using Win32 APIs.
Named Pipe
Naming an object helps the processes to share object handles. Names are case sensitive. Named objects are kernel objects. Kernel objects are process specific, and the process needs to be created or opened before using them.
Pipes are FIFO in behavior (First-In, First-Out). Pipes are of two types – Anonymous Pipes and Named Pipes.
An Anonymous Pipe is created using the CreatePipe()
API. An anonymous pipe is local, and cannot be used to communicate over a network. An anonymous pipe is unnamed, one-way, and generally used to transfer data from a parent process to a child process.
Named pipes can be one-way or duplex. Named pipes will work between processes on the same computer as well as between processes across the network.
Following are some of the Win32 APIs that are used when working with Named Pipes:
CreateNamedPipe()
ConnectNamedPipe()
WaitNamedPipe()
DisconnectNamedPipe()
ReadFile()
WriteFile()
CloseHandle()
A Named Pipe name needs to be in the following format:
- For named pipe server - \\.\pipe\PipeName
- For named pipe client - \\ComputerName\pipe\PipeName
The source code for a Named Pipe Server can be found in NPServer.zip, and for the client in NPClient.zip, both are downloadable from the links provided on the top of this article.
The code for a named pipe server is displayed below:
#include "stdafx.h" #include "windows.h" //Name given to the pipe #define g_szPipeName "\\\\.\\Pipe\\MyNamedPipe" //Pipe name format - \\.\pipe\pipename #define BUFFER_SIZE 1024 //1k #define ACK_MESG_RECV "Message received successfully" int main(int argc, char* argv[]) { HANDLE hPipe; hPipe = CreateNamedPipe( g_szPipeName, // 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 BUFFER_SIZE, // output buffer size BUFFER_SIZE, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out NULL); // default security attribute if (INVALID_HANDLE_VALUE == hPipe) { printf("\nError occurred while " "creating the pipe: %d", GetLastError()); return 1; //Error } else { printf("\nCreateNamedPipe() was successful."); } printf("\nWaiting for client connection..."); //Wait for the client to connect BOOL bClientConnected = ConnectNamedPipe(hPipe, NULL); if (FALSE == bClientConnected) { printf("\nError occurred while connecting" " to the client: %d", GetLastError()); CloseHandle(hPipe); return 1; //Error } else { printf("\nConnectNamedPipe() was successful."); } char szBuffer[BUFFER_SIZE]; DWORD cbBytes; //We are connected to the client. //To communicate with the client //we will use ReadFile()/WriteFile() //on the pipe handle - hPipe //Read client message BOOL bResult = ReadFile( hPipe, // handle to pipe szBuffer, // buffer to receive data sizeof(szBuffer), // size of buffer &cbBytes, // number of bytes read NULL); // not overlapped I/O if ( (!bResult) || (0 == cbBytes)) { printf("\nError occurred while reading " "from the client: %d", GetLastError()); CloseHandle(hPipe); return 1; //Error } else { printf("\nReadFile() was successful."); } printf("\nClient sent the following message: %s", szBuffer); strcpy(szBuffer, ACK_MESG_RECV); //Reply to client bResult = WriteFile( hPipe, // handle to pipe szBuffer, // buffer to write from strlen(szBuffer)+1, // number of bytes to write, include the NULL &cbBytes, // number of bytes written NULL); // not overlapped I/O if ( (!bResult) || (strlen(szBuffer)+1 != cbBytes)) { printf("\nError occurred while writing" " to the client: %d", GetLastError()); CloseHandle(hPipe); return 1; //Error } else { printf("\nWriteFile() was successful."); } CloseHandle(hPipe); return 0; //Success }
The code for a named pipe client is displayed below:
#include "stdafx.h" #include "windows.h" //Name given to the pipe #define g_szPipeName "\\\\.\\Pipe\\MyNamedPipe" //Pipe name format - \\servername\pipe\pipename //This pipe is for server on the same computer, //however, pipes can be used to //connect to a remote server #define BUFFER_SIZE 1024 //1k #define ACK_MESG_RECV "Message received successfully" int main(int argc, char* argv[]) { HANDLE hPipe; //Connect to the server pipe using CreateFile() hPipe = CreateFile( g_szPipeName, // 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 if (INVALID_HANDLE_VALUE == hPipe) { printf("\nError occurred while connecting" " to the server: %d", GetLastError()); //One might want to check whether the server pipe is busy //This sample will error out if the server pipe is busy //Read on ERROR_PIPE_BUSY and WaitNamedPipe() for that return 1; //Error } else { printf("\nCreateFile() was successful."); } //We are done connecting to the server pipe, //we can start communicating with //the server using ReadFile()/WriteFile() //on handle - hPipe char szBuffer[BUFFER_SIZE]; printf("\nEnter a message to be sent to the server: "); gets(szBuffer); DWORD cbBytes; //Send the message to server BOOL bResult = WriteFile( hPipe, // handle to pipe szBuffer, // buffer to write from strlen(szBuffer)+1, // number of bytes to write, include the NULL &cbBytes, // number of bytes written NULL); // not overlapped I/O if ( (!bResult) || (strlen(szBuffer)+1 != cbBytes)) { printf("\nError occurred while writing" " to the server: %d", GetLastError()); CloseHandle(hPipe); return 1; //Error } else { printf("\nWriteFile() was successful."); } //Read server response bResult = ReadFile( hPipe, // handle to pipe szBuffer, // buffer to receive data sizeof(szBuffer), // size of buffer &cbBytes, // number of bytes read NULL); // not overlapped I/O if ( (!bResult) || (0 == cbBytes)) { printf("\nError occurred while reading" " from the server: %d", GetLastError()); CloseHandle(hPipe); return 1; //Error } else { printf("\nReadFile() was successful."); } printf("\nServer sent the following message: %s", szBuffer); CloseHandle(hPipe); return 0; //Success }
Notes on Named Pipe:
- The source code is platform dependent.
- A named pipe is easy to use.
- A named pipe works across the network.
WinSock
WinSock provides very high level networking capabilities. It supports TCP/IP (the most widely used protocol), along with many other protocols – AppleTalk, DECNet, IPX/SPX etc.
WinSock supports Berkeley sockets, along with many other Windows specific extensions.
Following are some of the WinSock calls:
socket()
bind()
listen()
accept()
connect()
send()
recv()
Notes on WinSock:
- Widely used, and works on the same computer as well as across networks. Moreover, it can be used across various platforms and protocols.
- Using WinSock requires a knowledge of relatively advanced networking concepts. The source code demonstrating the use of a TCP/IP based one-to-one client and server can be found on my other article: A simple application using I/O Completion Port and WinSock.
Mailslot
Mailslot is used for one way inter-process communications. There is a Mailslot server which will be read-only; it will just read the client sent messages. The clients will be write-only clients, sending messages to the server. Mailslot messages can be of around 400 bytes only.
Mailslot can broadcast messages in a domain. If processes in a domain create a mailslot with the same name, then a message that is sent to that mailslot is sent to all of these processes.
Following are some of the Win32 APIs that are used when working with Mailslot:
CreateMailSlot()
GetMailslotInfo()
SetMailslotInfo()
ReadFile()
WriteFile()
CloseHandle()
A Mailslot name needs to be in the following format:
- \\ComputerName\mailslot\[path\]name
- \\DomainName\mailslot\[path\]name
- \\*\mailslot\[path\]name
Source code for a Mailslot server can be found in MSServer.zip, and for a client in MSClient.zip – download these from the links on the top of this article.
The code for a Mailslot server is displayed below:
#include "stdafx.h" #include "windows.h" //Name given to the Mailslot #define g_szMailslot "\\\\.\\mailslot\\MyMailSlot" //Mailslot name format - \\.\mailslot\mailslotname #define BUFFER_SIZE 1024 //1k int main(int argc, char* argv[]) { HANDLE hMailslot; hMailslot = CreateMailslot( g_szMailslot, // mailslot name BUFFER_SIZE, // input buffer size MAILSLOT_WAIT_FOREVER, // no timeout NULL); // default security attribute if (INVALID_HANDLE_VALUE == hMailslot) { printf("\nError occurred while" " creating the mailslot: %d", GetLastError()); return 1; //Error } else { printf("\nCreateMailslot() was successful."); } //Mailslot is one-way communication //Server will only read //Using ReadFile() char szBuffer[BUFFER_SIZE]; DWORD cbBytes; BOOL bResult; printf("\nWaiting for client connection..."); while(1) //Infinite, till user terminates the console app { //Read client message bResult = ReadFile( hMailslot, // handle to mailslot szBuffer, // buffer to receive data sizeof(szBuffer), // size of buffer &cbBytes, // number of bytes read NULL); // not overlapped I/O if ( (!bResult) || (0 == cbBytes)) { printf("\nError occurred while reading" " from the client: %d", GetLastError()); CloseHandle(hMailslot); return 1; //Error } else { printf("\nReadFile() was successful."); } printf("\nClient sent the following message: %s", szBuffer); } CloseHandle(hMailslot); return 0; //Success }
The code for a Mailslot client is displayed below:
#include "stdafx.h" #include "windows.h" //Name given to the Mailslot #define g_szMailslot "\\\\.\\mailslot\\MyMailSlot" //Mailslot name format - \\.\mailslot\mailslotname //This mailslot is for server on the same computer, //however, mailslots can be used to //connect to a remote server #define BUFFER_SIZE 1024 //1k int main(int argc, char* argv[]) { HANDLE hMailslot; //Connect to the server mailslot using CreateFile() hMailslot = CreateFile( g_szMailslot, // mailslot name GENERIC_WRITE, // mailslot write only FILE_SHARE_READ, // required for mailslots NULL, // default security attributes OPEN_EXISTING, // opens existing mailslot FILE_ATTRIBUTE_NORMAL, // normal attributes NULL); // no template file if (INVALID_HANDLE_VALUE == hMailslot) { printf("\nError occurred while connecting" " to the server: %d", GetLastError()); return 1; //Error } else { printf("\nCreateFile() was successful."); } //We are done connecting to the mailslot, //Mailslot communication is one-way, //client will just write to mailslot //Using WriteFile() char szBuffer[BUFFER_SIZE]; printf("\nEnter a message to be sent to the server: "); gets(szBuffer); DWORD cbBytes; //Send the message to server BOOL bResult = WriteFile( hMailslot, // handle to mailslot szBuffer, // buffer to write from strlen(szBuffer)+1, // number of bytes to write, include the NULL &cbBytes, // number of bytes written NULL); // not overlapped I/O if ( (!bResult) || (strlen(szBuffer)+1 != cbBytes)) { printf("\nError occurred while writing" " to the server: %d", GetLastError()); CloseHandle(hMailslot); return 1; //Error } else { printf("\nWriteFile() was successful."); } CloseHandle(hMailslot); return 0; //Success }
Notes on Mailslot
- Source code is platform dependent.
- Mailslot provides one-way communication only.
- Size of message is limited to around 400 bytes.
- Mailslot supports broadcasting.
- Works across a network.
- Mailslot is easy to use.
Conclusion
To conclude, this article is a brief introduction to Windows IPC mechanisms. I have tried to list the options available, and provided some code to help readers get a feel of how to use Windows IPC mechanisms. The article is not very exhaustive or detailed. The reader will need to refer to other detailed material on this topic to understand Windows IPC in a much better way.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
'C & C++ > MFC Network' 카테고리의 다른 글
간단한 FTP 프로그램 (0) | 2013.11.14 |
---|---|
포털 사이트 및 웹페이지 자동 로그인 프로그램 (0) | 2013.11.14 |
[Web] 하이퍼 링크 (0) | 2011.12.14 |
[Web] 웹사이트에 접속하여 원하는 HTML 문서 얻는법 (0) | 2011.12.14 |
[Web] 웹브라우져 팁 (0) | 2011.05.25 |
댓글