C++ 进程间通信(管道)
进程间通信(封装级别)、可拿入项目中直接使用!!!!!
**
PipeCS.h文件
**
#pragma once
#include <Windows.h>
#include <string>
#include <thread>
#include <iostream>
#include <atomic>
#include <iostream>class CPipeBase
{public:CPipeBase() = default;virtual ~CPipeBase() = default;typedef std::function<void(const std::string &szMsg)> TMessageHandler;protected:bool ReadPipe(HANDLE hNamedPipe, std::string &szMsg);bool WritePipe(HANDLE hNamedPipe, const std::string &szMsg);
};class CPipeServer : public CPipeBase
{public:CPipeServer(const std::string &szPipeName, TMessageHandler fnMsgHandler);CPipeServer(const CPipeServer &Other) = delete;CPipeServer(CPipeServer &&Other) = delete;~CPipeServer();CPipeServer& operator=(const CPipeServer &Other) = delete;CPipeServer& operator=(CPipeServer &&Other) = delete;void Run();void Stop();bool SendMsg(const std::string &szMsg);private:bool ConnectClient();void DisconnectClient();bool CreatePipeInstance(const std::string &szPipeName, HANDLE &hPipeInstance);void Close();private:std::string m_szPipeName;TMessageHandler m_fnMsgHandler;HANDLE m_hNamedPipeR;HANDLE m_hNamedPipeW;
};class CPipeClient : public CPipeBase
{public:CPipeClient(const std::string &szPipeName, TMessageHandler fnMsgHandler);CPipeClient(const CPipeClient &Other) = delete;CPipeClient(CPipeClient &&Other) = delete;~CPipeClient();CPipeClient& operator=(const CPipeClient &Other) = delete;CPipeClient& operator=(CPipeClient &&Other) = delete;bool IsConnected() const;bool Connect(unsigned int nTimeoutSeconds);void Disconnect();bool SendMsg(const std::string &szMsg);protected:bool SetMessageMode(HANDLE hNamedPipe);void ReadThreadProc();private:std::string m_szPipeName;HANDLE m_hNamedPipeW;HANDLE m_hNamedPipeR;// 消息读取线程std::atomic_bool m_bThreadRun = false;std::thread m_ReadThread;TMessageHandler m_fnMsgHandler;
};
**
PipeCS.cpp文件
**
#include "PipeCS.h"#define PIPE_BUF_SIZE 1024bool CPipeBase::WritePipe(HANDLE hNamedPipe, const std::string &szMsg)
{if (hNamedPipe == INVALID_HANDLE_VALUE){std::cout << "the pipe is invalid." << std::endl;return false;}DWORD dwWritedBytes = 0;DWORD dwTotalBytes = szMsg.size();DWORD dwSentBytes = 0;BOOL bResult = FALSE;do{bResult = ::WriteFile(hNamedPipe, &szMsg[dwSentBytes], dwTotalBytes - dwSentBytes, &dwWritedBytes, NULL);if (!bResult || dwWritedBytes == 0){std::cout << "write message to pipe error: " << ::GetLastError() << std::endl;return false;}dwSentBytes += dwWritedBytes;} while (dwSentBytes < dwTotalBytes);return true;
}bool CPipeBase::ReadPipe(HANDLE hNamedPipe, std::string &szMsg)
{szMsg.clear();if (hNamedPipe == INVALID_HANDLE_VALUE){std::cout << "the pipe is invalid." << std::endl;return false;}bool bResult = false;DWORD dwError = ERROR_SUCCESS;DWORD dwReadBytes = 0;CHAR ReadBuf[PIPE_BUF_SIZE] = { 0 };bool bReadMore = false;do{if (::ReadFile(hNamedPipe, ReadBuf, PIPE_BUF_SIZE, &dwReadBytes, NULL)){// 读成功,跳出szMsg.append(ReadBuf, dwReadBytes);bResult = true;break;}dwError = ::GetLastError();if (dwError == ERROR_MORE_DATA){// 没有读完,继续读szMsg.append(ReadBuf, dwReadBytes);bReadMore = true;continue;}// 其它错误,不再继续读bReadMore = false;if (dwError == ERROR_BROKEN_PIPE){std::cout << "the pipe has disconnected." << std::endl;}else{std::cout << "read message from pipe error: " << dwError << std::endl;}} while (bReadMore);return bResult;
}CPipeServer::CPipeServer(const std::string &szPipeName, TMessageHandler fnMsgHandler) :m_szPipeName(szPipeName), m_fnMsgHandler(fnMsgHandler)
{m_hNamedPipeR = INVALID_HANDLE_VALUE;m_hNamedPipeW = INVALID_HANDLE_VALUE;
}CPipeServer::~CPipeServer()
{Close();
}void CPipeServer::Run()
{std::cout << "pipe server will start." << std::endl;std::string szMsg;while (ConnectClient()){while (ReadPipe(m_hNamedPipeR, szMsg)){std::cout << "recv message success: " << szMsg;if (m_fnMsgHandler){m_fnMsgHandler(szMsg);}}DisconnectClient();}Close();std::cout << "pipe server will exit." << std::endl;
}void CPipeServer::Stop()
{Close();
}bool CPipeServer::SendMsg(const std::string &szMsg)
{std::cout << "send message: " << szMsg << std::endl;bool bSuccess = WritePipe(m_hNamedPipeW, szMsg);std::cout << "send message " << (bSuccess ? "success." : "failed.") << std::endl;return bSuccess;
}bool CPipeServer::ConnectClient()
{if (m_szPipeName.empty()){std::cout << "the pipe name is empty." << std::endl;return false;}std::string szFullName("\\\\.\\pipe\\");szFullName += m_szPipeName;std::cout << "create pipe server: " << m_szPipeName << std::endl;if (m_hNamedPipeR == INVALID_HANDLE_VALUE){if (!CreatePipeInstance(szFullName, m_hNamedPipeR)){std::cout << "create pipe server for read failed." << std::endl;return false;}std::cout << "create pipe server for read ok." << std::endl;}std::cout << "wait for the client to connect read ..." << std::endl;if (!::ConnectNamedPipe(m_hNamedPipeR, NULL)){DWORD dwError = ::GetLastError();if (dwError != ERROR_PIPE_CONNECTED){std::cout << "wait for the client to connect read error: " << dwError << std::endl;return false;}}std::cout << "client is connected." << std::endl;if (m_hNamedPipeW == INVALID_HANDLE_VALUE){if (!CreatePipeInstance(szFullName, m_hNamedPipeW)){std::cout << "create pipe server for write failed." << std::endl;return false;}std::cout << "create pipe server for write ok." << std::endl;}std::cout << "wait for the client to connect write ..." << std::endl;if (!::ConnectNamedPipe(m_hNamedPipeW, NULL)){DWORD dwError = ::GetLastError();if (dwError != ERROR_PIPE_CONNECTED){std::cout << "wait for the client to connect write error: " << dwError << std::endl;return false;}}std::cout << "connect pipe client success." << std::endl;return true;
}void CPipeServer::DisconnectClient()
{if (m_hNamedPipeR != INVALID_HANDLE_VALUE){::DisconnectNamedPipe(m_hNamedPipeR);}if (m_hNamedPipeW != INVALID_HANDLE_VALUE){::DisconnectNamedPipe(m_hNamedPipeW);}
}bool CPipeServer::CreatePipeInstance(const std::string &szPipeName, HANDLE &hPipeInstance)
{hPipeInstance = ::CreateNamedPipeA(szPipeName.c_str(),PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,2,PIPE_BUF_SIZE,PIPE_BUF_SIZE,0,NULL);if (hPipeInstance == INVALID_HANDLE_VALUE){std::cout << "create pipe server error: " << ::GetLastError() << std::endl;return false;}return true;
}void CPipeServer::Close()
{if (m_hNamedPipeR != INVALID_HANDLE_VALUE){::CloseHandle(m_hNamedPipeR);m_hNamedPipeR = INVALID_HANDLE_VALUE;}if (m_hNamedPipeW != INVALID_HANDLE_VALUE){::CloseHandle(m_hNamedPipeW);m_hNamedPipeW = INVALID_HANDLE_VALUE;}
}//
//CPipeClient::CPipeClient(const std::string &szPipeName, TMessageHandler fnMsgHandler) :m_szPipeName(szPipeName), m_fnMsgHandler(fnMsgHandler)
{m_hNamedPipeW = INVALID_HANDLE_VALUE;m_hNamedPipeR = INVALID_HANDLE_VALUE;
}CPipeClient::~CPipeClient()
{Disconnect();
}bool CPipeClient::IsConnected() const
{return (m_hNamedPipeW != INVALID_HANDLE_VALUE && m_hNamedPipeR != INVALID_HANDLE_VALUE);
}bool CPipeClient::Connect(unsigned int nTimeoutSeconds)
{if (IsConnected()){std::cout << "the pipe server is connected." << std::endl;return true;}if (m_szPipeName.empty()){std::cout << "the pipe server name is empty." << std::endl;return false;}std::string szFullName("\\\\.\\pipe\\");szFullName += m_szPipeName;std::cout << "connect to pipe server: " << m_szPipeName << " in " << nTimeoutSeconds << "s." << std::endl;int64_t nTimeoutMs = nTimeoutSeconds * 1000;DWORD dwError = ERROR_SUCCESS;do{// 先连接写管道,再连接读管道if (m_hNamedPipeW == INVALID_HANDLE_VALUE){m_hNamedPipeW = ::CreateFileA(szFullName.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);if (m_hNamedPipeW == INVALID_HANDLE_VALUE){dwError = ::GetLastError();}else{SetMessageMode(m_hNamedPipeW);}}else if (m_hNamedPipeR == INVALID_HANDLE_VALUE){m_hNamedPipeR = ::CreateFileA(szFullName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);if (m_hNamedPipeR == INVALID_HANDLE_VALUE){dwError = ::GetLastError();}else{SetMessageMode(m_hNamedPipeR);std::cout << "connect to pipe server ok." << std::endl;m_bThreadRun = true;m_ReadThread = std::thread(&CPipeClient::ReadThreadProc, this);return true;}}if (nTimeoutSeconds == 0){std::cout << "connect to pipe server error: " << dwError << std::endl;break;}if (nTimeoutMs <= 0){std::cout << "connect to pipe server timeout: " << dwError << std::endl;break;}std::this_thread::sleep_for(std::chrono::milliseconds(100));nTimeoutMs -= 100;} while (true);return false;
}void CPipeClient::Disconnect()
{if (m_hNamedPipeW != INVALID_HANDLE_VALUE){::CloseHandle(m_hNamedPipeW);m_hNamedPipeW = INVALID_HANDLE_VALUE;}if (m_hNamedPipeR != INVALID_HANDLE_VALUE){::CloseHandle(m_hNamedPipeR);m_hNamedPipeR = INVALID_HANDLE_VALUE;}m_bThreadRun = false;if (m_ReadThread.joinable()){m_ReadThread.join();}
}bool CPipeClient::SendMsg(const std::string &szMsg)
{bool bSuccess = false;std::cout << "send message: " << szMsg << std::endl;if (m_bThreadRun){bSuccess = WritePipe(m_hNamedPipeW, szMsg);}std::cout << "send message " << (bSuccess ? "success." : "failed.") << std::endl;return bSuccess;
}bool CPipeClient::SetMessageMode(HANDLE hNamedPipe)
{// 检查是否为消息模式DWORD dwMode = 0;if (!::GetNamedPipeHandleStateA(hNamedPipe, &dwMode, NULL, NULL, NULL, NULL, 0)){std::cout << "query the state of server error: " << ::GetLastError() << std::endl;return false;}if (dwMode != PIPE_READMODE_MESSAGE){dwMode = PIPE_READMODE_MESSAGE;if (!::SetNamedPipeHandleState(hNamedPipe, &dwMode, NULL, NULL)){std::cout << "change to message-read mode error: " << ::GetLastError() << std::endl;return false;}}std::cout << "change to message-read mode ok." << std::endl;return true;
}void CPipeClient::ReadThreadProc()
{std::cout << "read message thread begin." << std::endl; while (m_bThreadRun){std::string szMsg;if (!ReadPipe(m_hNamedPipeR, szMsg)){m_bThreadRun = false;break;}if (szMsg.empty()){continue;}if (m_fnMsgHandler){m_fnMsgHandler(szMsg);}}std::cout << "read message thread end." << std::endl;
}
C++ 进程间通信(管道)相关推荐
- Linux下进程间通信——管道
进程间通信 一.进程间通信 1.进程间通信--管道 (1)有名管道的创建 (2)有名管道的操作 写操作 读操作 发生阻塞和关闭程序的几种情况 2.无名管道的创建 (1)无名管道的操作 3.管道读取数据 ...
- 操作系统实验报告9:进程间通信—管道和 socket 通信
操作系统实验报告9 实验内容 实验内容:进程间通信-管道和 socket 通信. 编译运行课件 Lecture11 例程代码: alg.11-3-socket-input-2.c alg.11-4-s ...
- #Linux#进程间通信# 管道(pipe)-标准流管道pipe
在#Linux#进程间通信# 管道(pipe)-普通管道pipe中,我们很容易可以看出普通管道一是单工,即只能单向传输,而标准流管道针对匿名管道PIPE一系列封装.返回文件流.只不过返回的文件流无法使 ...
- linux学习:进程间通信—管道
1.进程间通信当中一种比較简单的方法是管道操作 /*========================================================================== ...
- Unix网络编程--进程间通信--管道通信
所有式样的Unix都提供管道,它由 pipe 函数创建,提供一个单路(单向)数据流. 原型如下: #include <unistd.h> int pipe(int ...
- [OS] 进程间通信--管道
管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起.写进程在管道的尾端写入数据,读进程在管道的首端读出数据.数据读出后将从管道中移走,其它读进 ...
- Linux进程间通信——管道
转自:http://www.cnblogs.com/feisky/archive/2010/03/24/1693484.html Linux进程间通信机制: 1.同一主机进程间通信机制: Unix方式 ...
- Linux进程间通信(管道、消息队列、共享内存、信号、信号量)
目录 Linux进程间通信概述 1.管道 无名管道(pipe) 有名管道(fifo) 2.消息队列(msg) 消息队列的通信原理 消息队列相关api 消息队列收发数据 键值生成 消息队列移除 3.共享 ...
- Linux系统【四】进程间通信-管道
进程间通信(IPC Interprocess Communication) 进程和进程之间的通信只能通过内核,在内核中提供一块缓冲区进行通信.内核提供的这种机制叫做IPC 在进程间完成数据传输需要借助 ...
- 进程间通信管道进阶篇:linux下dup/dup2函数的用法
由于利用管道实现进程间通信,是通过创建两个文件描述符,但是描述符的初始化是通过随机的,就是从可用的文件描述符中取出,并将可用的文件描述符与file对象相关联,如果我们需要将管道的两头与其他的流相关时, ...
最新文章
- Android安卓程序开发的权限设置
- 【机器学习】 ID3,C4.5,CART决策树
- php xdebug 教程视频_PHP Xdebug 是什么?
- 百度入股汽车照明模组晶合光电
- 顺丰同城:拟通过香港IPO发行1.31亿股H股 预期将于12月14日在港交所上市
- Git版本管理工具常用命令整理和说明
- 1.c语言的基本框架,C语言基本程序框架
- Unity的超大开放世界解决方案
- linux安装ipk游戏,添加软件包 IPK
- Cisco ❀ QinQ技术与VXLAN技术的区别
- 浅谈 Mlp-Mixer(pytorch and keras)
- 干货丨让你更容易影响别人的 52 个小技巧
- 升级LTS长期支持版|奇点云数据云平台发布DataSimba R3.8
- HDU - 1546 Idiomatic Phrases Game(dijkstra最短路)
- 数据挖掘实践 —— OneR 分类算法
- 不规则多边形重心求解
- 贾扬清官宣:从阿里离职,或将投身AI创业!
- mysql修改游戏元宝_页游源码【武斗乾坤】自带安装启动教程+元宝游戏数据修改教程+自由一键游戏启动服务端...
- 小日本的恶趣味?育碧让玩家用VR外设闻屁味
- arduino使用oled代码_Arduino提高篇04—U8g2库驱动OLED
热门文章
- python 炒股公式_计算股票公式
- could not initialize proxy - the owning Session was closed解决
- 奇技淫巧(二)—— 不使用中间变量交换两个值
- 2021-2027全球与中国环卫云平台市场现状及未来发展趋势
- 无插件使用Eclipse和Resin调试WEB应用(Debug Web App In Ecli...
- 如何做投资--入门篇
- C语言算法题:一只小蜜蜂...
- D - 一只小蜜蜂...
- 东原服务器开机显示bb,启用tls后,服务器出现remote error: tls: bad certificate
- 考研英语单词-近义词分类-Fourth Day