Win32 命名管道

编程入门 行业动态 更新时间:2024-10-11 21:23:53

Win32 命名<a href=https://www.elefans.com/category/jswz/34/1771259.html style=管道"/>

Win32 命名管道

命名管道简单封装

CNamedPipe.h

#pragma once
#include <string>
#include <windows.h>
#include <tchar.h>#pragma warning(disable:4200)class CNamedPipe
{
public:CNamedPipe();~CNamedPipe();CNamedPipe(const CNamedPipe& r) = delete;CNamedPipe& operator = (const CNamedPipe& r) = delete;//// @brief: 创建命名管道// @param: lpName           管道名// @ret: bool               true: 创建成功 false: 创建失败bool Create(LPCTSTR lpName);//// @brief: 等待客户端连接命名管道// @param: nTimeOut         超时等待(毫秒)// @ret: bool               true: 连接成功 false: 连接失败bool WaitConnect(DWORD nTimeOut = INFINITE);//// @brief: 关闭由Create 创建的管道// @param: void// @ret: bool               true: 关闭 成功 false: 关闭 失败bool Disconnect();//// @brief: 打开已存在的命名管道// @param: lpName           管道名// @ret: bool               true: 打开成功 false: 打开失败bool Open(LPCTSTR lpName, DWORD nTimeOut = INFINITE);//// @brief: 管道是否有效// @param: void// @ret: bool               true: 可用 false: 无效bool IsValid();//// @brief: 关闭管道// @param: void// @ret: voidvoid Close(void);//// @brief: 从读取管道数据// @param: lpData           数据存放缓冲// @param: nSize            缓冲大小(字节)// @param: lpBytesRead      指向实际读取大小(字节)的指针// @param: nTimeOut         读取超时(毫秒)// @ret: bool               true: 读取成功 false: 读取失败bool Read(LPVOID lpData, DWORD nSize, LPDWORD lpBytesRead = nullptr, DWORD nTimeOut = INFINITE);//// @brief: 向管道写入数据// @param: lpData           写入数据指针// @param: nSize            写入数据大小(字节)// @param: lpBytesWritten   指向实际写入大小(字节)的指针// @param: nTimeOut         写入超时(毫秒)// @ret: bool               true: 写入成功 false: 写入失败bool Write(LPCVOID lpData, DWORD nSize, LPDWORD lpBytesWritten = nullptr, DWORD nTimeOut = INFINITE);private://// @brief: 初始化对象占用// @param: void// @ret: voidbool Initialize();//// @brief: 释放对象占用// @param: void// @ret: voidvoid Uninitialize();private:HANDLE m_hNamedPipe;HANDLE m_hReadEvent;HANDLE m_hWriteEvent;LPVOID m_pBuffer;bool m_bInit;bool m_bConnected;
};

CNamedPipe.cpp

#include "CNamedPipe.h"
#include <StrSafe.h>
#include <tchar.h>#define PIPE_NAME_PREFIX             TEXT(R"(\\.\pipe\)")    //管道前缀名
#define PIPE_MAX_TIMEOUT             (3000)                  //管道打开超时
#define PIPE_BUF_MAX_SIZE            (1024 * 1024)           //管道发送缓冲大小(字节)
#define PIPE_MAX_CONNECT             (16)                    //IPC最大连接数typedef struct _PIPE_DATA
{DWORD dwSize = 0;BYTE data[0];
}PIPE_DATA, * PPIPE_DATA;CNamedPipe::CNamedPipe():m_hNamedPipe(INVALID_HANDLE_VALUE),m_hReadEvent(NULL),m_hWriteEvent(NULL),m_bConnected(false),m_bInit(false)
{//初始化读写缓冲与事件句柄Initialize();
}CNamedPipe::~CNamedPipe()
{//释放读写缓冲与事件句柄Uninitialize();
}bool CNamedPipe::Create(LPCTSTR lpName)
{TCHAR szPipeName[MAX_PATH];SECURITY_ATTRIBUTES sa = { 0 };SECURITY_DESCRIPTOR sd = { 0 };bool isSuccess = false;sa.nLength = sizeof(sa);sa.bInheritHandle = FALSE;sa.lpSecurityDescriptor = &sd;if (INVALID_HANDLE_VALUE != m_hNamedPipe){return true;}//设置权限, 防止低权限进程不能打开高权限进程创建的管道(void)::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);(void)::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);(void)::StringCchPrintf(szPipeName, _countof(szPipeName), TEXT("%s%s"), PIPE_NAME_PREFIX, lpName);do{m_hNamedPipe = ::CreateNamedPipe(szPipeName,PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,PIPE_MAX_CONNECT,PIPE_BUF_MAX_SIZE,PIPE_BUF_MAX_SIZE,PIPE_MAX_TIMEOUT,&sa);if (INVALID_HANDLE_VALUE == m_hNamedPipe){break;}isSuccess = true;} while (false);if (!isSuccess){this->Close();}return isSuccess;
}bool CNamedPipe::Open(LPCTSTR lpName, DWORD nTimeOut/* = INFINITE*/)
{TCHAR szPipeName[MAX_PATH] = { 0 };bool isSuccess = false;(void)::StringCchPrintf(szPipeName, _countof(szPipeName), TEXT("%s%s"), PIPE_NAME_PREFIX, lpName);if (INVALID_HANDLE_VALUE != m_hNamedPipe){return true;}ULONGLONG ullCurTick = ::GetTickCount64();do{m_hNamedPipe = ::CreateFile(szPipeName,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);//管道句柄有效则终止循环if (INVALID_HANDLE_VALUE != m_hNamedPipe){isSuccess = true;break;}//若错误原因不是因为所有管道范例都在使用中, 则退出循环if (ERROR_PIPE_BUSY != ::GetLastError()){break;}//等待命名管道的实例可用于连接if (::WaitNamedPipe(szPipeName, 1000)){continue;}//无限等待则不需要检查超时if (INFINITE == nTimeOut){continue;}//执行操作超时则退出循环if (::GetTickCount64() - ullCurTick > nTimeOut){break;}} while (INVALID_HANDLE_VALUE == m_hNamedPipe);if (!isSuccess){this->Close();}return isSuccess;
}bool CNamedPipe::WaitConnect(DWORD nTimeOut)
{OVERLAPPED Overlapped = { 0 };bool isConnected = false;if (INVALID_HANDLE_VALUE == m_hNamedPipe){return false;}Overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);if (NULL == Overlapped.hEvent){return false;}isConnected = ::ConnectNamedPipe(m_hNamedPipe, &Overlapped);if (!isConnected){DWORD dwError = ::GetLastError();//管道关闭中if (ERROR_NO_DATA == dwError){isConnected = false;}//操作处于挂起状态if (ERROR_IO_PENDING == dwError){if (WAIT_OBJECT_0 == ::WaitForSingleObject(Overlapped.hEvent, nTimeOut)){isConnected = true;}}//管道已经连接if (ERROR_PIPE_CONNECTED == dwError){isConnected = true;}}if (NULL != Overlapped.hEvent){::CloseHandle(Overlapped.hEvent);}m_bConnected = isConnected;return isConnected;
}bool CNamedPipe::Disconnect()
{if (INVALID_HANDLE_VALUE == m_hNamedPipe){return false;}//参数句柄必须由 CreateNamedPipe 函数创建return ::DisconnectNamedPipe(m_hNamedPipe);
}void CNamedPipe::Close()
{if (INVALID_HANDLE_VALUE != m_hNamedPipe){if (m_bConnected){::FlushFileBuffers(m_hNamedPipe);::DisconnectNamedPipe(m_hNamedPipe);m_bConnected = false;}::CloseHandle(m_hNamedPipe);m_hNamedPipe = INVALID_HANDLE_VALUE;}
}bool CNamedPipe::IsValid()
{return INVALID_HANDLE_VALUE != m_hNamedPipe;
}bool CNamedPipe::Read(LPVOID lpData, DWORD nSize, LPDWORD lpBytesRead/* = nullptr*/, DWORD nTimeOut)
{OVERLAPPED Overlapped = { 0 };Overlapped.hEvent = m_hReadEvent;DWORD dwBytesTransferred = 0;bool isSuccess = false;if (nullptr == m_pBuffer ||nullptr == lpData ||0 == nSize ||nSize > PIPE_BUF_MAX_SIZE){return false;}PPIPE_DATA pData = (PPIPE_DATA)m_pBuffer;if (!::ReadFile(m_hNamedPipe, &pData->dwSize, sizeof(PIPE_DATA), NULL, &Overlapped)){//管道已结束if (ERROR_BROKEN_PIPE == ::GetLastError()){return false;}if (ERROR_IO_PENDING != ::GetLastError()){return false;}if (WAIT_OBJECT_0 != ::WaitForSingleObject(Overlapped.hEvent, nTimeOut)){return false;}}if (pData->dwSize > PIPE_BUF_MAX_SIZE){return false;}if (!::ReadFile(m_hNamedPipe, pData->data, pData->dwSize, NULL, &Overlapped)){if (ERROR_IO_PENDING != ::GetLastError()){return false;}if (WAIT_OBJECT_0 != ::WaitForSingleObject(Overlapped.hEvent, nTimeOut)){return false;}}if (::GetOverlappedResult(m_hNamedPipe, &Overlapped, &dwBytesTransferred, true)){isSuccess = true;if (lpBytesRead){*lpBytesRead = dwBytesTransferred;}}if (isSuccess){if (nSize < pData->dwSize){::memcpy_s(lpData, nSize, pData->data, nSize);}else{::memcpy_s(lpData, nSize, pData->data, pData->dwSize);}}return isSuccess;
}bool CNamedPipe::Write(LPCVOID lpData, DWORD nSize, LPDWORD lpBytesWritten/* = nullptr*/, DWORD nTimeOut)
{OVERLAPPED Overlapped = { 0 };Overlapped.hEvent = m_hWriteEvent;DWORD dwBytesTransferred = 0;bool isSuccess = false;if (nullptr == m_pBuffer ||nullptr == lpData ||0 == nSize ||nSize > PIPE_BUF_MAX_SIZE){return false;}PPIPE_DATA pData = (PPIPE_DATA)m_pBuffer;DWORD dwBytesToWrite = nSize + sizeof(PIPE_DATA);pData->dwSize = nSize;::memcpy_s(pData->data, PIPE_BUF_MAX_SIZE, lpData, nSize);if (::WriteFile(m_hNamedPipe, pData, dwBytesToWrite, NULL, &Overlapped)){return true;}//管道正在被关闭if (ERROR_NO_DATA == ::GetLastError()){return false;}//管道已结束if (ERROR_BROKEN_PIPE == ::GetLastError()){return false;}//重叠if (ERROR_IO_PENDING != ::GetLastError()){return false;}if (WAIT_OBJECT_0 != ::WaitForSingleObject(Overlapped.hEvent, nTimeOut)){return false;}if (::GetOverlappedResult(m_hNamedPipe, &Overlapped, &dwBytesTransferred, true)){isSuccess = true;if (lpBytesWritten){*lpBytesWritten = dwBytesTransferred;}}return isSuccess;
}bool CNamedPipe::Initialize()
{bool isSuccess = false;if (m_bInit){return true;}do{if (nullptr == m_pBuffer){m_pBuffer = ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, PIPE_BUF_MAX_SIZE + sizeof(PIPE_DATA));}if (nullptr == m_pBuffer){break;}if (NULL == m_hReadEvent){m_hReadEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);}if (NULL == m_hReadEvent){break;}if (NULL == m_hWriteEvent){m_hWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);}if (NULL == m_hWriteEvent){break;}isSuccess = true;} while (false);if (!isSuccess){Uninitialize();}m_bInit = isSuccess;return m_bInit;
}void CNamedPipe::Uninitialize()
{if (!m_bInit){return;}//关闭管道this->Close();//释放读写缓冲if (nullptr != m_pBuffer){::HeapFree(::GetProcessHeap(), 0, m_pBuffer);m_pBuffer = nullptr;}//关闭事件if (m_hReadEvent){CloseHandle(m_hReadEvent);m_hReadEvent = NULL;}if (m_hWriteEvent){CloseHandle(m_hWriteEvent);m_hWriteEvent = NULL;}m_bInit = false;
}

main.cpp

#include <iostream>
#include "Utils/CNamedPipe.h"
#include <thread>
#include <future>int main()
{std::promise<bool> p;std::future<bool> f = p.get_future();std::thread([&p]() {static char szBuf[1024 * 64] = { 0 };CNamedPipe pipe;if (!pipe.Create(_T("FlameCyclone"))){std::cout << "Create failed!" << std::endl;p.set_value(false);return;}p.set_value(true);if (!pipe.WaitConnect()){std::cout << "WaitConnect failed!" << std::endl;return;}while (true){bool isSuccess = pipe.Read(szBuf, sizeof(szBuf));if (isSuccess){std::cout << "recv: " << szBuf << std::endl;}//另一端断开则重新等待连接if (ERROR_BROKEN_PIPE == ::GetLastError()){pipe.Disconnect();if (!pipe.WaitConnect()){std::cout << "WaitConnect failed!" << std::endl;return;}}}}).detach();if (!f.get()){return -1;}CNamedPipe pipe;if (!pipe.Open(_T("FlameCyclone"), 5000)){std::cout << "Open failed!" << std::endl;return -1;}std::string strMsg;while (true){std::cin >> strMsg;std::cout << "send: " << strMsg << std::endl;if (!pipe.Write(strMsg.c_str(), strMsg.size() + 1)){std::cout << "Write failed!" << std::endl;break;}}system("pause");return 0;
}

更多推荐

Win32 命名管道

本文发布于:2023-12-04 17:27:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1661678.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:管道

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!