1. 命名管道(Named Pipes)
1.1. 概述
命名管道是一种用于进程间通信的机制,允许数据在进程之间以管道的形式进行传输。命名管道可以在同一台计算机上或通过网络连接的计算机之间使用。
1.2. 特点
双向通信:命名管道支持同时发送和接收数据。
异步和同步操作:支持客户端和服务器的非阻塞和阻塞操作。
网络支持:可用于不同计算机间的通信。
安全性:可以设置访问权限,确保数据的安全性。
1.3. 实现方式
1.3.1. 服务器端示例
#include <windows.h>
#include <iostream>int main() {// 创建命名管道HANDLE hPipe = CreateNamedPipe(L"\\\\.\\pipe\\MyNamedPipe", // 命名管道名称PIPE_ACCESS_DUPLEX, // 双向访问PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, // 消息管道PIPE_UNLIMITED_INSTANCES, // 实例数量512, 512, 0, NULL); // 缓冲区大小if (hPipe == INVALID_HANDLE_VALUE) {std::cerr << "创建命名管道失败" << std::endl;return 1;}std::cout << "等待客户端连接..." << std::endl;// 等待客户端连接if (ConnectNamedPipe(hPipe, NULL) != FALSE) {std::cout << "客户端已连接。" << std::endl;char buffer[128];DWORD bytesRead;// 从管道读取数据if (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {buffer[bytesRead] = '\0';std::cout << "从客户端收到消息: " << buffer << std::endl;// 向客户端发送回应const char* response = "Hello from server!";DWORD bytesWritten;WriteFile(hPipe, response, strlen(response), &bytesWritten, NULL);}}CloseHandle(hPipe);return 0;
}
1.3.2. 客户端示例
#include <windows.h>
#include <iostream>int main() {// 打开命名管道HANDLE hPipe = CreateFile(L"\\\\.\\pipe\\MyNamedPipe", // 与服务器端管道名称一致GENERIC_READ | GENERIC_WRITE, // 读写权限0, NULL, OPEN_EXISTING, 0, NULL);if (hPipe == INVALID_HANDLE_VALUE) {std::cerr << "连接到管道失败" << std::endl;return 1;}// 向服务器发送数据const char* message = "Hello from client!";DWORD bytesWritten;WriteFile(hPipe, message, strlen(message), &bytesWritten, NULL);char buffer[128];DWORD bytesRead;// 从服务器读取回应if (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {buffer[bytesRead] = '\0';std::cout << "从服务器收到消息: " << buffer << std::endl;}CloseHandle(hPipe);return 0;
}
1.4. 使用场景
适合:需要在不同进程之间传输消息或数据,特别是在客户端和服务器之间。
优点:易于实现、支持多客户端连接、提供一定的安全性。
2. 套接字(Sockets)
2.1. 概述
套接字是网络通信的基本概念,可以在同一台计算机上或跨网络的进程之间进行通信。可以使用 TCP 和 UDP 协议。
2.2. 特点
灵活性:可以支持不同的协议(TCP、UDP)。
跨平台:在不同操作系统之间的兼容性好。
可扩展性:适合构建分布式应用程序。
2.3. 实现方式
2.3.1. 服务器端(TCP 套接字)
#include <iostream>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")int main() {// 初始化 WinsockWSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);// 创建套接字SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY;serverAddr.sin_port = htons(8080);// 绑定套接字bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));// 监听连接listen(serverSocket, SOMAXCONN);std::cout << "等待客户端连接..." << std::endl;sockaddr_in clientAddr;int clientAddrSize = sizeof(clientAddr);SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrSize);if (clientSocket != INVALID_SOCKET) {std::cout << "客户端已连接。" << std::endl;char buffer[128];int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);if (bytesReceived > 0) {buffer[bytesReceived] = '\0';std::cout << "收到客户端消息: " << buffer << std::endl;// 发送回应const char* response = "Hello from server!";send(clientSocket, response, strlen(response), 0);}closesocket(clientSocket);}closesocket(serverSocket);WSACleanup();return 0;
}
2.3.2. 客户端(TCP 套接字)
#include <iostream>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")int main() {// 初始化 WinsockWSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);// 创建套接字SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP 地址serverAddr.sin_port = htons(8080);// 连接到服务器connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));// 发送数据const char* message = "Hello from client!";send(clientSocket, message, strlen(message), 0);char buffer[128];int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);if (bytesReceived > 0) {buffer[bytesReceived] = '\0';std::cout << "收到服务器消息: " << buffer << std::endl;}closesocket(clientSocket);WSACleanup();return 0;
}
2.4. 使用场景
适合:需要在分布式环境中进行通信的应用,如网络服务、聊天程序等。
优点:支持多种协议,能够处理大量并发连接。
3. 共享内存(Shared Memory)
3.1. 概述
共享内存是一种高效的进程间通信方式,通过允许多个进程访问同一块内存区域来实现快速数据交换。
3.2. 特点
高性能:避免了数据复制,速度快。
实时性:适合需要快速、实时数据交换的场景。
同步复杂性:需要额外的机制来防止数据冲突。
3.3. 实现方式
3.3.1. 服务器端(共享内存)
#include <windows.h>
#include <iostream>int main() {// 创建共享内存HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, // 使用分页文件NULL, // 默认安全属性PAGE_READWRITE, // 可读写0, // 高位文件大小256, // 低位文件大小L"MySharedMemory"); // 共享内存名称if (hMapFile == NULL) {std::cerr << "创建共享内存失败" << std::endl;return 1;}// 映射共享内存LPCTSTR pBuf = (LPTSTR)MapViewOfFile(hMapFile, // 共享内存句柄FILE_MAP_ALL_ACCESS, // 读写访问0, // 高位偏移0, // 低位偏移256); // 映射大小if (pBuf == NULL) {std::cerr << "映射共享内存失败" << std::endl;CloseHandle(hMapFile);return 1;}// 写入数据到共享内存CopyMemory((PVOID)pBuf, L"Hello from server!", sizeof(L"Hello from server!"));std::cout << "数据写入共享内存。" << std::endl;// 等待用户输入以保持共享内存std::cin.get();UnmapViewOfFile(pBuf);CloseHandle(hMapFile);return 0;
}
3.3.2. 客户端(共享内存)
#include <windows.h>
#include <iostream>int main() {// 打开共享内存HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, // 读写访问FALSE, // 不继承句柄L"MySharedMemory"); // 共享内存名称if (hMapFile == NULL) {std::cerr << "打开共享内存失败" << std::endl;return 1;}// 映射共享内存LPCTSTR pBuf = (LPTSTR)MapViewOfFile(hMapFile, // 共享内存句柄FILE_MAP_ALL_ACCESS, // 读写访问0, // 高位偏移0, // 低位偏移256); // 映射大小if (pBuf == NULL) {std::cerr << "映射共享内存失败" << std::endl;CloseHandle(hMapFile);return 1;}// 读取共享内存中的数据std::wcout << L"从共享内存读取数据: " << pBuf << std::endl;UnmapViewOfFile(pBuf);CloseHandle(hMapFile);return 0;
}
3.4. 使用场景
适合:高性能、实时数据交换需求,如视频流处理、实时数据分析。
优点:高效,适合大规模数据传输。