c+++下の名前付きパイプを使ってプロセス間通信を実現します.

9532 ワード

前にすでに郵便スロットを使ってプロセス間通信を実現しました.http://www.cnblogs.com/jzincnblogs/p/5192654.html ,ここでは名前付きパイプを使ってプロセス間通信を実現します.
郵便スロットとは違って、名前付きパイプがプロセス間でデータを転送するのは、接続に基づいて信頼できる伝送方式であるため、パイプと名付けられたデータはペアだけである.名前付きパイプを使う手順は以下の通りです.
①名前付きパイプを作成し、名前付きパイプを関数CreateNamedPipe()を呼び出して作成しました.関数の原型は以下の通りです.
 1 HANDLE WINAPI CreateNamedPipe(
 2   _In_     LPCTSTR               lpName,
 3   _In_     DWORD                 dwOpenMode,
 4   _In_     DWORD                 dwPipeMode,
 5   _In_     DWORD                 nMaxInstances,
 6   _In_     DWORD                 nOutBufferSize,
 7   _In_     DWORD                 nInBufferSize,
 8   _In_     DWORD                 nDefaultTimeOut,
 9   _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
10 );
各パラメータの設定方法はMSDNを参照できます.https://msdn.microsoft.com/zh-cn/biztalk/aa365150(v=vs.80)
②命名配管を接続する.ユーザが名前付きパイプを成功裏に作成すると、関連関数接続の命名パイプを呼び出すことができます.サーバにとっては、関数Connect NamedPipe()を呼び出してクライアントの接続要求を待つことができます.関数の原型は以下の通りです.
1 BOOL WINAPI ConnectNamedPipe(
2   _In_        HANDLE       hNamedPipe,
3   _Inout_opt_ LPOVERLAPPED lpOverlapped
4 );
パラメータの設定方法:https://msdn.microsoft.com/zh-cn/biztalk/aa365150(v=vs.80)
クライアントにとっては、接続サーバが作成したネーミングパイプの前で、このネーミングパイプが利用可能かどうかを判断する必要があり、関数WaitNamedPipe()を呼び出して実装することができ、関数の使用方法はMSDNを参照することができる.https://msdn.microsoft.com/zh-cn/subscriptions/aa365800
WaitNamedPipe()の呼び出しが成功すると、CreateFile()を使用して、配管名を付けて取得したハンドルを開くことができます.
③名前付きパイプを読んで書き、名前付きパイプの読み書き操作は関数ReadFile()とWriteFile()で行い、前編の郵便スロットと似ています.
サーバとクライアントの実現コードは以下の通りです.
サーバ端:
 1 //server
 2 //                 ,       
 3 #include <windows.h>
 4 #include <iostream>
 5 
 6 #define BUF_SIZE 1024
 7 
 8 using std::cerr;
 9 using std::cout;
10 using std::endl;
11 
12 int main()
13 {
14     HANDLE h_pipe;
15     char buf_msg[BUF_SIZE];
16     DWORD num_rcv; //         
17     //      ,   MyPipe,             ,          ,     ,     0       50  
18     h_pipe = ::CreateNamedPipe("\\\\.\\pipe\\MyPipe", PIPE_ACCESS_INBOUND, PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUF_SIZE, BUF_SIZE, 0, nullptr);
19     if (h_pipe == INVALID_HANDLE_VALUE)
20     {
21         cerr << "Failed to create named pipe!Error code: " << ::GetLastError() << "
"; 22 system("pause"); 23 return 1; 24 } 25 else 26 { 27 cout << "Named pipe created successfully...
"; 28 } 29 // 30 if (::ConnectNamedPipe(h_pipe, nullptr)) 31 { 32 cout << "A client connected...
"; 33 memset(buf_msg, 0, BUF_SIZE); 34 // 35 if (::ReadFile(h_pipe, buf_msg, BUF_SIZE, &num_rcv, nullptr)) 36 { 37 cout << "Message received: " << buf_msg << "
"; 38 } 39 else 40 { 41 cerr << "Failed to receive message!Error code: " << ::GetLastError() << "
"; 42 ::CloseHandle(h_pipe); 43 ::system("pause"); 44 return 1; 45 } 46 } 47 ::CloseHandle(h_pipe); 48 ::system("pause"); 49 return 0; 50 }
クライアント:
 1 //client
 2 #include <windows.h>
 3 #include <iostream>
 4 
 5 #define BUF_SIZE 1024
 6 
 7 using std::cerr;
 8 using std::cout;
 9 using std::endl;
10 
11 int main()
12 {
13     HANDLE h_pipe;
14     char buf_msg[] = "Test for named pipe...";
15     DWORD num_rcv; //         
16     cout << "Try to connect named pipe...
"; 17 // 18 if (::WaitNamedPipe("\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER)) 19 { 20 // 21 h_pipe = ::CreateFile("\\\\.\\pipe\\MyPipe", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 22 if (h_pipe == INVALID_HANDLE_VALUE) 23 { 24 cerr << "Failed to open the appointed named pipe!Error code: " << ::GetLastError() << "
"; 25 ::system("pause"); 26 return 1; 27 } 28 else 29 { 30 if (::WriteFile(h_pipe, buf_msg, BUF_SIZE, &num_rcv, nullptr)) 31 { 32 cout << "Message sent successfully...
"; 33 } 34 else 35 { 36 cerr << "Failed to send message!Error code: " << ::GetLastError() << "
"; 37 ::CloseHandle(h_pipe); 38 ::system("pause"); 39 return 1; 40 } 41 } 42 ::CloseHandle(h_pipe); 43 } 44 ::system("pause"); 45 return 0; 46 }