• windows下C++管道通信


    windows下C++管道通信

      在windows下,可通过Vs Studio中的C++ CMake创建管道通信的demo。
      工程文件结构如下:

    pipe_communication_test
        pipe_server.cpp
        pipe_client.cpp
        CMakeLists.txt
        CMakePresets.json    //使用Vs Studio创建CMake项目时,自动生成的文件
    
    • 1
    • 2
    • 3
    • 4
    • 5

    服务端“pipe_server.cpp”

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    #define BUFSIZE 128
    
    class Pipe_Server {
    public:
    	Pipe_Server(std::string pipe_name, std::function<std::string(std::string)> callBackFun) {
    		pipe_name_ = "\\\\.\\Pipe\\";
    		pipe_name_ += pipe_name;
    		if (pipe_name == "") {
    			std::cout << "pipe name is empty" << std::endl;
    			return;
    		}
    		std::cout << "Create pipe server: " << pipe_name << std::endl;
    
    		callBackFun_ = callBackFun;
    
    		std::thread run_thread(std::bind(&Pipe_Server::run, this));
    		run_thread.detach();
    	}
    	~Pipe_Server() {}
    
    private:
    	//待绑定的回调函数
    	std::function<std::string(std::string)> callBackFun_;
    	std::string pipe_name_;
    
    	WCHAR* toWChar(const char* c) {
    		WCHAR wszClassName[256];
    		memset(wszClassName, 0, sizeof(wszClassName));
    		MultiByteToWideChar(CP_ACP, 0, c, strlen(c) + 1, wszClassName,
    			sizeof(wszClassName) / sizeof(wszClassName[0]));
    		return wszClassName;
    	}
    
    	void run() {
    		
    		while (1) {
    			HANDLE hPipe = CreateNamedPipe(pipe_name_.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT
    				, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, 0);
    
    			//waiting to be connected
    			if (ConnectNamedPipe(hPipe, NULL) != NULL) {
    				std::cout << "连接成功,开始发送数据" << std::endl;
    
    				//接收服务端发回的数据
    				BOOL fSuccess = false;
    				DWORD len = 0;
    				char buffer[BUFSIZE];
    				string recvData = "";
    				while (true) {
    					fSuccess = ReadFile(hPipe, buffer, BUFSIZE * sizeof(char), &len, NULL);
    					char buffer2[BUFSIZE + 1] = { 0 };
    					memcpy(buffer2, buffer, len);
    					recvData.append(buffer2);
    					if (!fSuccess || len < BUFSIZE)
    						break;
    				}
    				std::cout << "recv data: \n" << recvData.c_str() << std::endl;
    
    				std::string res_msg = callBackFun_(recvData);
    
    				DWORD dwWrite;
    				char* pStr = nullptr;
    				pStr = new char(res_msg.size() + 1);    //存在内存泄露
    				strcpy(pStr, res_msg.c_str());    //将string转变成char*
    				if (!WriteFile(hPipe, pStr, strlen(pStr), &dwWrite, NULL)) {
    					std::cout << "write failed..." << std::endl;
    					DisconnectNamedPipe(hPipe);
    					CloseHandle(hPipe);//关闭管道
    					std::cout << "结束一次管道通信" << std::endl;
    
    					//delete pStr;    //造成程序错误
    
    					break;
    				}
    				else {
    					std::cout << "send data: \n" << pStr << std::endl;
    					DisconnectNamedPipe(hPipe);
    					CloseHandle(hPipe);//关闭管道
    
    					//delete pStr;    //造成程序错误
    
    					std::cout << "结束一次管道通信" << std::endl;
    				}
    			}
    			else {
    				std::cout << "pipe connect failed" << std::endl;
    				Sleep(1000);
    			}
    		}
    	}
    };
    
    std::string msgProcess(std::string msg) {
    	std::string return_msg = msg;
    	return_msg += " test";
    
    	std::cout << "process msg" << std::endl;
    
    	return return_msg;
    }
    
    
    int main() {
    	std::cout << "pipe server" << std::endl;
    
    	Pipe_Server pipe_server("pipe", std::bind(msgProcess, std::placeholders::_1));
    
    	while (1) {
    		Sleep(1000);
    	}
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    客户端“pipe_client.h”

    #include 
    #include 
    #include 
    #include 
    
    #define BUFSIZE 128
    
    class Pipe_Client {
    public:
    	Pipe_Client(std::string pipe_name) {
    		pipe_name_ = "\\\\.\\Pipe\\";
    		pipe_name_ += pipe_name;
    		if (pipe_name == "") {
    			//LOG(ERROR) << "pipe name is empty";
    			std::cout << "pipe name is empty" << std::endl;
    			return;
    		}
    
    		std::cout << "pipe name is: " << pipe_name << std::endl;
    	}
    
    	~Pipe_Client() {}
    
    	std::string sendAndGetMsg(std::string send_msg) {
    		if (WaitNamedPipe(pipe_name_.c_str(), NMPWAIT_WAIT_FOREVER) == FALSE) {
    			//LOG(INFO) << "EEEEEEEEE";
    			std::cout << "wait pipe failed" << std::endl;
    			return "";
    		}
    
    		//LOG(INFO) << "打开命名管道: " << pipe_name_;
    		std::cout << "打开命名管道: " << pipe_name_ << std::endl;
    		HANDLE hPipe = CreateFile(pipe_name_.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
    			NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    		if ((long)hPipe == -1) {
    			std::cout << "打开管道失败" << std::endl;
    			return "";
    		}
    
    		//发送数据
    		DWORD    dwWrite;
    		static char* pStr = nullptr;
    		if (pStr != nullptr) {
    			delete pStr;
    		}
    		pStr = new char(send_msg.size() + 1);
    		strcpy(pStr, send_msg.c_str());    //将string转变成char*
    		if (!WriteFile(hPipe, pStr, strlen(pStr), &dwWrite, NULL)) {
    			std::cout << "write failed..." << std::endl << std::endl;
    			return "";
    		}
    		std::cout << "sent data: " << std::endl << pStr << std::endl << std::endl;
    		Sleep(400);
    
    		//接收服务端发回的数据
    		BOOL fSuccess = false;
    		DWORD len = 0;
    		char buffer[BUFSIZE];
    		std::string recvData = "";
    		while (true) {
    			fSuccess = ReadFile(hPipe, buffer, BUFSIZE * sizeof(char), &len, NULL);
    			char buffer2[BUFSIZE + 1] = { 0 };
    			memcpy(buffer2, buffer, len);
    			recvData.append(buffer2);
    			if (!fSuccess || len < BUFSIZE)
    				break;
    		}
    		std::cout << "recv data:" << std::endl << recvData.c_str() << std::endl << std::endl;
    
    		FlushFileBuffers(hPipe);
    		DisconnectNamedPipe(hPipe);
    		CloseHandle(hPipe);
    
    		return recvData;
    	}
    
    private:
    	std::string pipe_name_;
    };
    
    std::string msgProcess(std::string msg) {
    	std::string return_msg;
    
    	return return_msg;
    }
    
    
    int main() {
    	std::cout << "pipe client" << std::endl;
    
    	Pipe_Client pipe_client("pipe");
    	std::cout << "rec: " << pipe_client.sendAndGetMsg("qwer");
    
    	while (1) {
    		Sleep(1000);
    	}
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    CMake文件“CMakeList.txt”

    # CMakeList.txt: create_process_test 的 CMake 项目,在此处包括源代码并定义
    # 项目特定的逻辑。
    #
    cmake_minimum_required (VERSION 3.8)
    
    project ("pipe_communication_test")
    
    add_executable(pipe_server pipe_server.cpp)
    add_executable(pipe_client pipe_client.cpp)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意事项

    1. pipe_server.cpp中存在内存泄漏的问题,暂时没有解决;
    2. 只能使用VsStudio的CMake进行编译,否则无法完成编译;
  • 相关阅读:
    研究了11种实时聊天软件,我发现都具备这些功能…
    golang单线程对比map与bigCache小对象存取性能差别
    PingCode 完成近亿元人民币C轮融资,打造世界级研发管理与协作平台
    C++编译静态成员函数报错: “osgGA::DriveManipulator::setEye”: 非静态成员函数的非法调用
    Linux bash脚本编程学习
    rsync远程同步
    自定义表单验证规则 (自定义一个方法)
    使用记账软件记录生活收支明细,如何防止收支不被他人修改
    【Hack The Box】windows练习-- Timelapse
    2020最新Java面试题
  • 原文地址:https://blog.csdn.net/weixin_43879302/article/details/131730713