进程间通信(封装级别)、可拿入项目中直接使用!!!!!

**

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++ 进程间通信(管道)相关推荐

  1. Linux下进程间通信——管道

    进程间通信 一.进程间通信 1.进程间通信--管道 (1)有名管道的创建 (2)有名管道的操作 写操作 读操作 发生阻塞和关闭程序的几种情况 2.无名管道的创建 (1)无名管道的操作 3.管道读取数据 ...

  2. 操作系统实验报告9:进程间通信—管道和 socket 通信

    操作系统实验报告9 实验内容 实验内容:进程间通信-管道和 socket 通信. 编译运行课件 Lecture11 例程代码: alg.11-3-socket-input-2.c alg.11-4-s ...

  3. #Linux#进程间通信# 管道(pipe)-标准流管道pipe

    在#Linux#进程间通信# 管道(pipe)-普通管道pipe中,我们很容易可以看出普通管道一是单工,即只能单向传输,而标准流管道针对匿名管道PIPE一系列封装.返回文件流.只不过返回的文件流无法使 ...

  4. linux学习:进程间通信—管道

    1.进程间通信当中一种比較简单的方法是管道操作 /*========================================================================== ...

  5. Unix网络编程--进程间通信--管道通信

          所有式样的Unix都提供管道,它由 pipe 函数创建,提供一个单路(单向)数据流.       原型如下: #include <unistd.h> int pipe(int ...

  6. [OS] 进程间通信--管道

    管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起.写进程在管道的尾端写入数据,读进程在管道的首端读出数据.数据读出后将从管道中移走,其它读进 ...

  7. Linux进程间通信——管道

    转自:http://www.cnblogs.com/feisky/archive/2010/03/24/1693484.html Linux进程间通信机制: 1.同一主机进程间通信机制: Unix方式 ...

  8. Linux进程间通信(管道、消息队列、共享内存、信号、信号量)

    目录 Linux进程间通信概述 1.管道 无名管道(pipe) 有名管道(fifo) 2.消息队列(msg) 消息队列的通信原理 消息队列相关api 消息队列收发数据 键值生成 消息队列移除 3.共享 ...

  9. Linux系统【四】进程间通信-管道

    进程间通信(IPC Interprocess Communication) 进程和进程之间的通信只能通过内核,在内核中提供一块缓冲区进行通信.内核提供的这种机制叫做IPC 在进程间完成数据传输需要借助 ...

  10. 进程间通信管道进阶篇:linux下dup/dup2函数的用法

    由于利用管道实现进程间通信,是通过创建两个文件描述符,但是描述符的初始化是通过随机的,就是从可用的文件描述符中取出,并将可用的文件描述符与file对象相关联,如果我们需要将管道的两头与其他的流相关时, ...

最新文章

  1. Android安卓程序开发的权限设置
  2. 【机器学习】 ID3,C4.5,CART决策树
  3. php xdebug 教程视频_PHP Xdebug 是什么?
  4. 百度入股汽车照明模组晶合光电
  5. 顺丰同城:拟通过香港IPO发行1.31亿股H股 预期将于12月14日在港交所上市
  6. Git版本管理工具常用命令整理和说明
  7. 1.c语言的基本框架,C语言基本程序框架
  8. Unity的超大开放世界解决方案
  9. linux安装ipk游戏,添加软件包 IPK
  10. Cisco ❀ QinQ技术与VXLAN技术的区别
  11. 浅谈 Mlp-Mixer(pytorch and keras)
  12. 干货丨让你更容易影响别人的 52 个小技巧
  13. 升级LTS长期支持版|奇点云数据云平台发布DataSimba R3.8
  14. HDU - 1546 Idiomatic Phrases Game(dijkstra最短路)
  15. 数据挖掘实践 —— OneR 分类算法
  16. 不规则多边形重心求解
  17. 贾扬清官宣:从阿里离职,或将投身AI创业!
  18. mysql修改游戏元宝_页游源码【武斗乾坤】自带安装启动教程+元宝游戏数据修改教程+自由一键游戏启动服务端...
  19. 小日本的恶趣味?育碧让玩家用VR外设闻屁味
  20. arduino使用oled代码_Arduino提高篇04—U8g2库驱动OLED

热门文章

  1. python 炒股公式_计算股票公式
  2. could not initialize proxy - the owning Session was closed解决
  3. 奇技淫巧(二)—— 不使用中间变量交换两个值
  4. 2021-2027全球与中国环卫云平台市场现状及未来发展趋势
  5. 无插件使用Eclipse和Resin调试WEB应用(Debug Web App In Ecli...
  6. 如何做投资--入门篇
  7. C语言算法题:一只小蜜蜂...
  8. D - 一只小蜜蜂...
  9. 东原服务器开机显示bb,启用tls后,服务器出现remote error: tls: bad certificate
  10. 考研英语单词-近义词分类-Fourth Day