Windows API提供了郵槽和命名管道兩種機制來實現進程間通訊,在這裏使用C++實現郵槽。ios
郵槽是Windows提供的一種進程間單向通訊的機制,進程中的一方只能讀取(或寫入)數據,而另外一方只能寫入(或讀取)數據。這種進程間的通訊能夠發生在本地或者網絡之中。而在使用郵槽以前,服務器端必須先建立郵槽,建立的函數原型以下:編程
1 HANDLE WINAPI CreateMailslot( 2 _In_ LPCTSTR lpName, 3 _In_ DWORD nMaxMessageSize, 4 _In_ DWORD lReadTimeout, 5 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes 6 );
其中參數lpName表示郵槽的名稱。郵槽名稱的格式爲"\\.\mailslot\YourMailslotName",其中YourMailslotName由用戶指定。須要注意的是,在實際編碼中反斜槓須要轉義;參數nMaxMessageSize表示發送的消息大小的最大值,若設置爲0則表示大小爲任意值。(實際上郵槽能傳輸的數據很是小,通常400KB,若數據過大,郵槽可能沒法正常工做);參數lReadTimeout表示讀取操做的超時時間;參數lpSecurityAttributes表示郵槽的安全屬性,置爲NULL表示使用默認的安全屬性。windows
客戶端在使用郵槽前必須先打開郵槽,經過函數CreateFile()實現,函數原型以下:安全
1 HANDLE WINAPI CreateFile( 2 _In_ LPCTSTR lpFileName, 3 _In_ DWORD dwDesiredAccess, 4 _In_ DWORD dwShareMode, 5 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 6 _In_ DWORD dwCreationDisposition, 7 _In_ DWORD dwFlagsAndAttributes, 8 _In_opt_ HANDLE hTemplateFile 9 );
參數的具體設置方法可參考MSDN給出的解釋:服務器
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx 網絡
須要注意的是,指定要打開的郵槽時,若程序是在不一樣主機上運行的,郵槽名稱中的點號"."須要改爲對方主機的名稱。app
在實際的編程過程當中,對郵槽的操做與文件同樣,都是經過調用函數ReadFile()和WriteFile()實現的,函數原型以下:函數
1 BOOL WINAPI ReadFile( 2 _In_ HANDLE hFile, 3 _Out_ LPVOID lpBuffer, 4 _In_ DWORD nNumberOfBytesToRead, 5 _Out_opt_ LPDWORD lpNumberOfBytesRead, 6 _Inout_opt_ LPOVERLAPPED lpOverlapped 7 ); 8 9 BOOL WINAPI WriteFile( 10 _In_ HANDLE hFile, 11 _In_ LPCVOID lpBuffer, 12 _In_ DWORD nNumberOfBytesToWrite, 13 _Out_opt_ LPDWORD lpNumberOfBytesWritten, 14 _Inout_opt_ LPOVERLAPPED lpOverlapped 15 );
其中參數lpNumberOfBytesWritten是一個指向DWORD類型的指針,表示實際讀取/寫入的字節數。編碼
最終實現的代碼以下,實現面向對象的方法實現:spa
服務器端:
1 //header.h 2 #ifndef HEADER_H 3 #define HEADER_H 4 5 #include <windows.h> 6 7 #define BUFFER_SIZE 1024 8 9 class MailServer 10 { 11 public: 12 MailServer(); 13 MailServer(const MailServer &) = delete; 14 MailServer & operator=(const MailServer &) = delete; 15 ~MailServer(); 16 void ReadMail(); 17 private: 18 HANDLE h_mail; 19 char buffer[BUFFER_SIZE]; 20 DWORD exact_read_num; //指向實際讀取的字節數的指針 21 }; 22 23 #endif
1 //definition.cpp 2 #include "header.h" 3 #include <iostream> 4 5 MailServer::MailServer() 6 { 7 //郵槽的命名格式爲"\\.\mailslot\YourMailslotName",反斜槓須要轉義,採用非阻塞式讀取方法 8 h_mail = ::CreateMailslot("\\\\.\\mailslot\\MyMailSlot", 0, 0, nullptr); 9 if (h_mail == INVALID_HANDLE_VALUE) 10 { 11 std::cerr << "Failed to create a mailslot!\n"; 12 ::system("pause"); 13 exit(1); 14 } 15 else 16 { 17 std::cout << "Mailslot created successfully..." << std::endl; 18 } 19 } 20 21 MailServer::~MailServer() 22 { 23 ::CloseHandle(h_mail); 24 std::cout << "Mailslot closed..." << std::endl; 25 } 26 27 void MailServer::ReadMail() 28 { 29 std::cout << "Reading mail from mailslot..." << std::endl; 30 while (true) 31 { 32 if (::ReadFile(h_mail, buffer, BUFFER_SIZE, &exact_read_num, nullptr)) 33 { 34 std::cout << "New mail: " << buffer << std::endl; 35 } 36 } 37 }
1 //server.cpp 2 #include "header.h" 3 4 int main() 5 { 6 MailServer mail_svr; 7 mail_svr.ReadMail(); 8 system("pause"); 9 return 0; 10 }
客戶端:
1 //header.h 2 #ifndef HEADER_H 3 #define HEADER_H 4 5 #include "windows.h" 6 7 #define BUFFER_SIZE 1024 8 9 class MailClient 10 { 11 public: 12 MailClient(); 13 MailClient(const MailClient &) = delete; 14 MailClient & operator=(const MailClient &) = delete; 15 ~MailClient(); 16 void SendMail(); 17 private: 18 HANDLE h_mail; 19 char buffer[BUFFER_SIZE]; 20 DWORD exact_write_num; 21 }; 22 23 #endif
1 //definition.cpp 2 #include "header.h" 3 #include <iostream> 4 5 MailClient::MailClient() 6 { 7 h_mail = ::CreateFile("\\\\.\\mailslot\\MyMailSlot", GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 8 if (h_mail == INVALID_HANDLE_VALUE) 9 { 10 std::cerr << "Failed to create a mailslot!\n"; 11 system("pause"); 12 exit(1); 13 } 14 else 15 { 16 std::cout << "Mailslot created successfully..." << std::endl; 17 } 18 } 19 20 MailClient::~MailClient() 21 { 22 ::CloseHandle(h_mail); 23 std::cout << "Mailslot closed..." << std::endl; 24 } 25 26 void MailClient::SendMail() 27 { 28 while (true) 29 { 30 std::cout << "Please write a mail: " << std::flush; 31 std::cin.getline(buffer, BUFFER_SIZE); 32 if (strcmp(buffer, "exit") == 0) 33 { 34 std::cout << "User requests to close the mailslot..." << std::endl; 35 break; 36 } 37 else 38 { 39 if (::WriteFile(h_mail, buffer, BUFFER_SIZE, &exact_write_num, nullptr)) 40 { 41 std::cout << "Mail sent successfully..." << std::endl; 42 } 43 else 44 { 45 std::cerr << "Failed to send the mail...\n"; 46 system("pause"); 47 exit(1); 48 } 49 } 50 } 51 }
1 #include "header.h" 2 3 int main() 4 { 5 MailClient mail_clt; 6 mail_clt.SendMail(); 7 system("pause"); 8 return 0; 9 }