前言
RPC相关信息,可自行百度。 以下是在学习阶段的时候,借助AI的力量生成的,用于个人学习使用,无任何版权纠纷。
运行环境:Linux。
服务端
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#pragma pack(push, 1)
struct Request {
uint32_t method_id; // 0=add, 1=multiply
int32_t a;
int32_t b;
};
struct Response {
int32_t result;
uint8_t success; // 1=成功, 0=失败
};
#pragma pack(pop)
const int PORT = 8080;
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
std::cerr << "Socket创建失败\n";
return 1;
}
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) {
std::cerr << "绑定失败\n";
return 1;
}
if (listen(server_fd, 3) < 0) {
std::cerr << "监听失败\n";
return 1;
}
std::cout << "服务端正在监听端口 " << PORT << std::endl;
while (true) {
sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_len);
if (client_fd < 0) {
std::cerr << "接受连接失败\n";
continue;
}
std::cout << "新客户端连接\n";
bool keep_connection = true;
while (keep_connection) {
Request req;
ssize_t bytes_received = read(client_fd, &req, sizeof(req));
if (bytes_received != sizeof(req)) {
if (bytes_received == 0) {
std::cout << "客户端关闭连接\n";
} else {
std::cerr << "读取请求失败,接收字节数: " << bytes_received << std::endl;
}
keep_connection = false;
break;
}
// 转换网络字节序到主机字节序
req.method_id = ntohl(req.method_id);
req.a = ntohl(req.a);
req.b = ntohl(req.b);
Response res;
res.success = 0;
switch (req.method_id) {
case 0: // add
std::cout << "处理加法请求: " << req.a << " + " << req.b << std::endl;
res.result = req.a + req.b;
res.success = 1;
break;
case 1: // multiply
std::cout << "处理乘法请求: " << req.a << " * " << req.b << std::endl;
res.result = req.a * req.b;
res.success = 1;
break;
default:
std::cerr << "未知方法ID: " << req.method_id << std::endl;
res.success = 0;
break;
}
// 转换result到网络字节序
res.result = htonl(res.result);
if (write(client_fd, &res, sizeof(res)) != sizeof(res)) {
std::cerr << "发送响应失败\n";
keep_connection = false;
break;
}
}
close(client_fd);
std::cout << "客户端连接已关闭\n";
}
close(server_fd);
return 0;
}
客户端
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#pragma pack(push, 1)
struct Request {
uint32_t method_id;
int32_t a;
int32_t b;
};
struct Response {
int32_t result;
uint8_t success;
};
#pragma pack(pop)
const char* SERVER_IP = "127.0.0.1";
const int PORT = 8080;
void clear_input() {
std::cin.clear();
std::cin.ignore(1024, '\n');
}
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
std::cerr << "Socket创建失败\n";
return 1;
}
sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) {
std::cerr << "地址无效\n";
close(sock);
return 1;
}
if (connect(sock, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "连接失败\n";
close(sock);
return 1;
}
while (true) {
std::cout << "\n==== RPC 客户端 ====\n";
std::cout << "1. 加法运算\n";
std::cout << "2. 乘法运算\n";
std::cout << "0. 退出\n";
std::cout << "请选择操作: ";
int choice;
if (!(std::cin >> choice)) {
std::cerr << "输入无效,请重新输入\n";
clear_input();
continue;
}
if (choice == 0) {
std::cout << "退出客户端\n";
break;
}
if (choice < 1 || choice > 2) {
std::cerr << "无效选项,请重新输入\n";
continue;
}
int a, b;
std::cout << "输入第一个操作数: ";
if (!(std::cin >> a)) {
std::cerr << "输入无效,请重新输入\n";
clear_input();
continue;
}
std::cout << "输入第二个操作数: ";
if (!(std::cin >> b)) {
std::cerr << "输入无效,请重新输入\n";
clear_input();
continue;
}
Request req;
req.method_id = htonl(static_cast<uint32_t>(choice - 1)); // 转换为0基索引
req.a = htonl(a);
req.b = htonl(b);
if (write(sock, &req, sizeof(req)) != sizeof(req)) {
std::cerr << "发送请求失败\n";
break;
}
Response res;
if (read(sock, &res, sizeof(res)) != sizeof(res)) {
std::cerr << "接收响应失败\n";
break;
}
res.result = ntohl(res.result);
if (res.success == 1) {
std::cout << "\n计算结果: " << res.result << std::endl;
} else {
std::cerr << "服务端处理失败\n";
}
}
close(sock);
return 0;
}