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
浙公网安备 33010602011771号