BufferedIpc
这是我以前写的一个做IPC的类。因为是C++的,所以仅做参考了。
对外有三个函数:
bool init(const string& name, int size, DWORD initTimeout) int send(LPVOID Buffer, int size) int receive(LPBYTE& Buffer)
任何一方调init时就建立file mapping了。init中的size只是缓冲区大小,这个大小发送方和接收方必须一致;实际发送接收时,如果超出缓冲区大小时会自动分多次发送;发送完一段之后接收方会收到一个event可以开始读入。然后发送方用send, 接收方receive就可以了。receive会在读完所有数据之后返回创建的buffer。
初始化时可以指定等待event的timeout时间。初始化之后无论谁发送接收都是可以的。
/////////////////////////////////////////////////////////////////////////////// class BufferedIpc { public: BufferedIpc() { id = 0; hCanWriteEvent[0] = hCanWriteEvent[1] = NULL; hCanReadEvent[0] = hCanReadEvent[1] = NULL; hFileMap = NULL; mapView = NULL; } ~BufferedIpc() { for(int i = 0; i < 2; i++) { if (hCanWriteEvent[i]) CloseHandle(hCanWriteEvent[i]); if (hCanReadEvent[i]) CloseHandle(hCanReadEvent[i]); } if (mapView) UnmapViewOfFile(mapView); if (hFileMap) CloseHandle(hFileMap); } //Init with a shared name (must be unique), and the maximum size that can send at once. bool init(const string& name, int size, DWORD initTimeout) { char buf[MAX_PATH]; shareName = name; bufferSize = size + sizeof(BufferHead); timeout = initTimeout; // First try to open mapped file hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shareName.c_str()); id = (hFileMap == NULL) ? 0 : 1; if (hFileMap == NULL) { // allocate a mapped file area for internal data storage // and for IPC buffer exchange hFileMap = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, NULL, bufferSize, shareName.c_str()); if (hFileMap == NULL) { return false; } } mapView = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, bufferSize); for(int i = 0; i < 2; i++) { sprintf(buf, "%s_CANWRITE_%d", shareName.c_str(), i); hCanWriteEvent[i] = fetchEvent(buf, TRUE); sprintf(buf, "%s_CANREAD_%d", shareName.c_str(), i); hCanReadEvent[i] = fetchEvent(buf, FALSE); } return true; } //No limit on the send and receive size. Return sent size. int send(LPVOID Buffer, int size) { BufferHead bh; bh.totalSize = size; bh.thisPackSize = 0; bh.remainSize = size; while(bh.remainSize > 0) { if (WaitForSingleObject(hCanWriteEvent[id], timeout) != WAIT_OBJECT_0) break; bh.thisPackSize = min(bufferSize - (int)sizeof(BufferHead), bh.remainSize); bh.remainSize -= bh.thisPackSize; //Write head. memcpy(mapView, &bh, sizeof(BufferHead)); // Then some memory. memcpy((LPBYTE)mapView + sizeof(BufferHead), (LPBYTE)Buffer + bh.totalSize - bh.remainSize - bh.thisPackSize, bh.thisPackSize); // Signal that there is something to read SetEvent(hCanReadEvent[1 - id]); } return bh.totalSize - bh.remainSize; } //Returns: bytes received, and buffer will be automatically allocated if received at least 1 byte. int receive(LPBYTE& Buffer) { BufferHead bh; bool first = true; Buffer = NULL; memset(&bh, 0, sizeof(bh)); // Anything there to read? while(true) { if (WaitForSingleObject(hCanReadEvent[id], timeout) != WAIT_OBJECT_0) break; // Read from mapped memory memcpy(&bh, mapView, sizeof(BufferHead)); if (first && bh.totalSize) { Buffer = new BYTE[bh.totalSize]; first = false; } if (bh.thisPackSize) memcpy((LPBYTE)Buffer + bh.totalSize - bh.remainSize - bh.thisPackSize, (LPBYTE)mapView + sizeof(BufferHead), bh.thisPackSize); SetEvent(hCanWriteEvent[1 - id]); if (bh.remainSize == 0) break; } return bh.totalSize; } protected: //The common shared name. used to create file, event. string shareName; //Id can only 0 or 1. If it created file, then 0. otherwise 1. int id; // Size of the mapping file. int bufferSize; //timeout while waiting for events. can be INFINITE. DWORD timeout; //Handle of the file map file. HANDLE hFileMap; LPVOID mapView; HANDLE hCanWriteEvent[2]; HANDLE hCanReadEvent[2]; //For large data pack, we need to separate the packages. Thus use this one. struct BufferHead { //Total data size. int totalSize; //This packet size. int thisPackSize; //Total size still remains. If it equals 0, then we are done. int remainSize; }; HANDLE fetchEvent(const string& name, BOOL signaled) { HANDLE h; // Try to open mutex h = OpenEvent(EVENT_ALL_ACCESS, FALSE, name.c_str()); // event not found ? create it if (h == NULL) h = CreateEvent(NULL, FALSE, signaled, name.c_str()); return h; } }; //BufferedIpc