2.3.2 主程序和外部IO交互 (文件映射方式)----IO Client C++实现
和IOServer主要差别:
1 使用Open_Client 连接
2 一定要先打开IOServer,再打开IO_Client
效果显示
1 C++ 代码实现
1.1 shareddataClient.h 头文件中引用
和shareddataServer.h 一样需要引入相应的头文件
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
#include <windows.h>
#elif defined(linux) || defined(__linux)
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif
1.2 shareddataClient.h 主要调用接口
1.2.1 预定义变量名称,为了能够Linux|Windows下通用
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#elif defined(linux) || defined(__linux)
typedef void *HANDLE;
typedef void *LPVOID;
typedef long long __int64;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef unsigned long long ULONG_PTR;
typedef unsigned long long *PULONG_PTR;
typedef int BOOL;
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
#endif
1.2.2 函数接口定义
namespace SHAREDDATA
{
typedef unsigned char uchar;
BD_API int GetIOData(uchar* p_IOData, int start, int len);
BD_API int SetIOData(uchar* p_IOData, int start, int len);
BD_API int SetDM8(uchar* p_DM8, int start, int len);
BD_API int GetDM8(uchar* p_DM8, int start, int len);
BD_API int GetDM16(uchar* p_DM16, int start, int len);
BD_API int SetDM16(uchar* p_DM16, int start, int len);
/**
* ***********************************************************************************************
* @brief ReleaseMMF
* 销毁资源
*
* @return BD_API
* ***********************************************************************************************
*/
BD_API void ReleaseMMF();
/**
* ***********************************************************************************************
* @brief
*
*
* @return BD_API
* ***********************************************************************************************
*/
BD_API int Open_Client();
1.3 shareddataClient.cpp 函数接口实现
namespace SHAREDDATA
{
#pragma region MMF 内存共享 IO 区
// 创建共享文件句柄
HANDLE hMapFile_IO = INVALID_HANDLE_VALUE;
// 文档句柄
int fd_io=-1;
#pragma endregion MMF 内存IO 区
#pragma region MMF 内存共享 DM8 区
// 创建共享文件句柄
HANDLE hMapFile_DM8 = INVALID_HANDLE_VALUE;
// 文档句柄
int fd_dm8=-1;
#pragma endregion MMF 内存DM8 区
#pragma region MMF 内存共享 DM16 区
// 创建共享文件句柄
HANDLE hMapFile_DM16 = INVALID_HANDLE_VALUE;
// 文档句柄
int fd_dm16=-1;
#pragma endregion MMF 内存DM16 区
}
/**
* SHAREDDATA
* 文件共享方式进行通讯
*/
namespace SHAREDDATA
{
LPVOID MapViewofFile_New(HANDLE handle,const int& fd, const int& size)
{
LPVOID lpBase=nullptr;
if(handle==nullptr||size==0)return lpBase;
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
// 映射缓存区视图 , 得到指向共享内存的指针
lpBase = MapViewOfFile(
handle, // 共享内存的句柄
FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
size
);
#elif defined(linux) || defined(__linux)
if(fd<0)return nullptr;
// map memory to file
lpBase = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
#endif
return lpBase;
}
void UnMapViewofFile_New(HANDLE handle,const int& size)
{
if(handle==nullptr||size==0)return ;
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
// 解除文件映射
UnmapViewOfFile(handle);
#elif defined(linux) || defined(__linux)
// unmap and close
munmap(handle, size);
#endif
return;
}
/**
* ***********************************************************************************************
* @brief
* Create_Server
* 创建一个server
*
* @return BD_API
* ***********************************************************************************************
*/
BD_API int Open_Client()
{
int nRet = 0;
try
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
hMapFile_IO = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, "ShareMemoryIO");
if (hMapFile_IO != INVALID_HANDLE_VALUE && hMapFile_IO>0)nRet = 0;
else return -1;
// &1 DM8
//&1 DM8
hMapFile_DM8 = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, "ShareMemoryDM8");
if (hMapFile_DM8 != INVALID_HANDLE_VALUE && hMapFile_DM8 > 0)nRet = 0;
else return -1;
// &2 DM16
hMapFile_DM16 = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, "ShareMemoryDM16");
if (hMapFile_DM16 != INVALID_HANDLE_VALUE && hMapFile_DM16 > 0)nRet = 0;
else return -1;
#elif defined(linux) || defined(__linux)
// specify shared file path
// 路径一定要存在,否则会报警
// &0 DMIO
string shared_file_io = path+"ShareMemoryIO";
fd_io = open(shared_file_io.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
if (fd_io < 0)
{cout << "create file error" << endl;return -1;
}
ftruncate(fd_io, n_max_IO_uchars); // extend file size
// &0 DM8
string shared_file_dm8 = path+"ShareMemoryDM8";
fd_dm8 = open(shared_file_dm8.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
if (fd_dm8 < 0)
{cout << "create file error" << endl;return -1;
}
ftruncate(fd_dm8, n_max_DM8s); // extend file size
// map memory to file
//hMapFile_DM8 = mmap(NULL, n_max_DM8s, , PROT_READ | PROT_WRITE, MAP_SHARED, fd_dm8, 0);
// &0 DM16
string shared_file_dm16= path+"ShareMemoryDM16";
fd_dm16 = open(shared_file_dm8.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
if (fd_dm16 < 0)
{cout << "create file error" << endl;return -1;
}
ftruncate(fd_dm16, n_max_DM16s); // extend file size
#endif
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
#pragma region 销毁共享文件 句柄
// 销毁内存 MMF 句柄
BD_API void ReleaseMMF()
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
if (hMapFile_IO != NULL)CloseHandle(hMapFile_IO);
if (hMapFile_DM8 != NULL)CloseHandle(hMapFile_DM8);
if (hMapFile_DM16 != NULL)CloseHandle(hMapFile_DM16);
#elif defined(linux) || defined(__linux)
if(fd_io>=0)close(fd_io);
if(fd_dm8>=0)close(fd_dm8);
if(fd_dm16>=0)close(fd_dm16);
#endif
}
#pragma endregion
}
namespace SHAREDDATA
{
#pragma region MappingMemoryFile 共享
/**
* ***********************************************************************************************
* @brief GetIOData
* 获取IO 输出
* @param[in] p_IOData Comment
* @param[in] start Comment
* @param[in] len Comment
*
* @return BD_API
* ***********************************************************************************************
*/
BD_API int GetIOData(uchar* p_IOData, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (len + start > n_max_IO_uchars)
{
len = n_max_IO_uchars - start;
}
if (len > 0)
{
LPVOID lpBase = MapViewofFile_New(hMapFile_IO,fd_io, n_max_IO_uchars);
// copy 内存
memcpy(p_IOData, (uchar*)lpBase, len);
//memcpy(p_IOData, b_IO, len);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_IO_uchars);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
/**
* ***********************************************************************************************
* @brief SetIOData
* 设置IO数据
* @param[in] p_IOData Comment
* @param[in] start Comment
* @param[in] len Comment
*
* @return BD_API
* ***********************************************************************************************
*/
BD_API int SetIOData(uchar* p_IOData, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (len + start > n_max_IO_uchars)
{
len = n_max_IO_uchars - start;
}
// len 一定》0
if (len > 0)
{
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewofFile_New(hMapFile_IO,fd_io, n_max_IO_uchars);
// copy 内存
memcpy((uchar*)lpBase, p_IOData, len);
//memcpy(b_IO, p_IOData, len);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_IO_uchars);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
/// @brief SetDM8
/// @param p_DM8
/// @param start
/// @param len
/// @return
BD_API int SetDM8(uchar* p_DM8, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (start > n_max_DM8s)
{
len = 0;
nRet = -1;
return nRet;
}
if (len + start > n_max_DM8s)
{
len = n_max_DM8s - start;
}
// len 一定》0
if (len > 0)
{
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewofFile_New(hMapFile_DM8,fd_dm8, n_max_DM8s);
memcpy((uchar*)lpBase + start, p_DM8, len);
//memcpy(DM_8 + start, p_DM8, len);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_DM8s);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
BD_API int GetDM8(uchar* p_DM8, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (start > n_max_DM8s)
{
nRet = -1;
return nRet;
}
if (len + start > n_max_DM8s)
{
len = n_max_DM8s - start;
}
// len 一定》0
if (len > 0)
{
if (hMapFile_DM8 == INVALID_HANDLE_VALUE)return -2;
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewofFile_New(hMapFile_DM8,fd_dm8, n_max_DM8s);
// copy 内存
memcpy(p_DM8, (uchar*)lpBase + start, len);
//memcpy(p_DM8, DM_8 + start, len);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_DM8s);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
BD_API int GetDM16(uchar* p_DM16, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (start * 2 > n_max_DM16s)
{
nRet = -1;
return nRet;
}
if (len + start > n_max_DM16s)
{
len = n_max_DM16s - start;
}
// len 一定》0
// 这里的 DM16 的地址 可能直接就是 int 类型的, 无需start *2
if (len > 0)
{
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewofFile_New(hMapFile_DM16,fd_dm16, n_max_DM8s);
// copy 内存
memcpy(p_DM16, (uchar*)lpBase + start, len*2);
//memcpy(p_DM16, DM_16 + start, len * 2);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_DM16s);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
BD_API int SetDM16(uchar* p_DM16, int start, int len)
{
int nRet = 0;
std::lock_guard<std::mutex> lock(_mutex);
try
{
if (start * 2 > n_max_DM16s)
{
len = 0;
nRet = -1;
return nRet;
}
if (len + start > n_max_DM16s)
{
len = n_max_DM16s - start;
}
// len 一定》0
// 这里的 DM16 的地址 可能直接就是 int 类型的, 无需start *2
if (len > 0)
{
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewofFile_New(hMapFile_DM16,fd_dm16, n_max_DM8s);
// copy 内存
memcpy((uchar*)lpBase + start, p_DM16, len*2);
//memcpy(DM_16 + start, p_DM16, len * 2);
// 解除文件映射
UnMapViewofFile_New(lpBase, n_max_DM16s);
}
else nRet = -1;
}
catch (exception& e)
{
nRet = -1;
}
return nRet;
}
#pragma endregion
}