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() {
// 初始化 Winsock
WSADATA 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() {
// 初始化 Winsock
WSADATA 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. 使用场景
适合:高性能、实时数据交换需求,如视频流处理、实时数据分析。
优点:高效,适合大规模数据传输。