7 changed files with 0 additions and 1843 deletions
@ -1,192 +0,0 @@ |
|||||
/*
|
|
||||
* rpc_client.c |
|
||||
* RPC客户端实现,连接到服务器并调用远程函数 |
|
||||
*/ |
|
||||
|
|
||||
#include "rpc_common.h" |
|
||||
#include "rpc_transport.h" |
|
||||
#include "rpc_message.h" |
|
||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
#include <io.h> |
|
||||
#include <direct.h> |
|
||||
#define access _access |
|
||||
#define stat _stat |
|
||||
#else |
|
||||
#include <unistd.h> |
|
||||
#include <sys/stat.h> |
|
||||
#include <time.h> |
|
||||
#endif |
|
||||
|
|
||||
/*
|
|
||||
* RPC客户端结构 |
|
||||
*/ |
|
||||
typedef struct { |
|
||||
rpc_transport_t transport; |
|
||||
bool connected; |
|
||||
} rpc_client_t; |
|
||||
|
|
||||
/*
|
|
||||
* 初始化RPC客户端 |
|
||||
*/ |
|
||||
int rpc_client_create(rpc_client_t* client, const char* server_host, uint16_t server_port) { |
|
||||
if (!client || !server_host) { |
|
||||
return RPC_INVALID_ARGS; |
|
||||
} |
|
||||
|
|
||||
memset(client, 0, sizeof(rpc_client_t)); |
|
||||
|
|
||||
// 连接到服务器
|
|
||||
int ret = rpc_client_init(&client->transport, server_host, server_port); |
|
||||
if (ret != RPC_SUCCESS) { |
|
||||
return ret; |
|
||||
} |
|
||||
|
|
||||
client->connected = true; |
|
||||
return RPC_SUCCESS; |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* 关闭RPC客户端 |
|
||||
*/ |
|
||||
void rpc_client_destroy(rpc_client_t* client) { |
|
||||
if (!client) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (client->connected) { |
|
||||
rpc_transport_close(&client->transport); |
|
||||
client->connected = false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* 从用户输入获取文件信息 |
|
||||
*/ |
|
||||
int get_file_info(char* file_path, size_t max_path_len) { |
|
||||
printf("请输入要操作的文件路径: "); |
|
||||
if (fgets(file_path, max_path_len, stdin) == NULL) { |
|
||||
printf("获取文件路径失败\n"); |
|
||||
return RPC_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 移除换行符
|
|
||||
size_t len = strlen(file_path); |
|
||||
if (len > 0 && file_path[len-1] == '\n') { |
|
||||
file_path[len-1] = '\0'; |
|
||||
} |
|
||||
|
|
||||
// 检查文件是否存在
|
|
||||
if (access(file_path, 0) != 0) { |
|
||||
printf("文件 %s 不存在\n", file_path); |
|
||||
return RPC_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 获取文件信息
|
|
||||
struct stat file_stat; |
|
||||
if (stat(file_path, &file_stat) != 0) { |
|
||||
printf("获取文件信息失败\n"); |
|
||||
return RPC_ERROR; |
|
||||
} |
|
||||
|
|
||||
printf("文件信息:\n"); |
|
||||
printf("- 路径: %s\n", file_path); |
|
||||
printf("- 大小: %lld 字节\n", (long long)file_stat.st_size); |
|
||||
printf("- 权限: %o\n", file_stat.st_mode & 0777); |
|
||||
printf("- 修改时间: %s", ctime(&file_stat.st_mtime)); |
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* 主函数 |
|
||||
*/ |
|
||||
int main(int argc, char* argv[]) { |
|
||||
const char* server_host = NULL; |
|
||||
uint16_t server_port = 0; |
|
||||
char file_path[256] = {0}; |
|
||||
|
|
||||
// 从命令行参数或用户输入获取服务器主机和端口
|
|
||||
if (argc >= 3) { |
|
||||
server_host = argv[1]; |
|
||||
server_port = atoi(argv[2]); |
|
||||
} else { |
|
||||
// 显示帮助信息
|
|
||||
printf("用法: rpc_client <server_host> <server_port>\n"); |
|
||||
printf("如果未提供参数,将使用交互式输入\n\n"); |
|
||||
|
|
||||
// 交互式输入服务器信息
|
|
||||
char host_input[256]; |
|
||||
char port_input[10]; |
|
||||
|
|
||||
printf("请输入远程服务器地址: "); |
|
||||
if (fgets(host_input, sizeof(host_input), stdin) == NULL) { |
|
||||
printf("获取服务器地址失败\n"); |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
// 移除换行符
|
|
||||
host_input[strcspn(host_input, "\n")] = '\0'; |
|
||||
server_host = host_input; |
|
||||
|
|
||||
printf("请输入远程服务器端口: "); |
|
||||
if (fgets(port_input, sizeof(port_input), stdin) == NULL) { |
|
||||
printf("获取服务器端口失败\n"); |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
// 移除换行符并转换为数字
|
|
||||
port_input[strcspn(port_input, "\n")] = '\0'; |
|
||||
server_port = atoi(port_input); |
|
||||
|
|
||||
if (server_port == 0) { |
|
||||
printf("无效的端口号,使用默认端口 8080\n"); |
|
||||
server_port = 8080; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
// 初始化Windows套接字库
|
|
||||
if (rpc_winsock_init() != RPC_SUCCESS) { |
|
||||
printf("初始化Winsock失败\n"); |
|
||||
return 1; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
printf("RPC客户端已启动\n"); |
|
||||
printf("连接到服务器 %s:%d...\n", server_host, server_port); |
|
||||
|
|
||||
// 初始化RPC客户端
|
|
||||
rpc_client_t client; |
|
||||
if (rpc_client_create(&client, server_host, server_port) != RPC_SUCCESS) { |
|
||||
printf("连接到服务器失败\n"); |
|
||||
#ifdef _WIN32 |
|
||||
rpc_winsock_cleanup(); |
|
||||
#endif |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
printf("成功连接到服务器\n"); |
|
||||
|
|
||||
// 获取文件信息
|
|
||||
if (get_file_info(file_path, sizeof(file_path)) != RPC_SUCCESS) { |
|
||||
printf("获取文件信息失败\n"); |
|
||||
} else { |
|
||||
printf("准备发送文件 %s 的信息到服务器\n", file_path); |
|
||||
// 这里可以添加将文件信息发送到服务器的代码
|
|
||||
} |
|
||||
|
|
||||
// 关闭RPC客户端
|
|
||||
rpc_client_destroy(&client); |
|
||||
printf("已关闭与服务器的连接\n"); |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
// 清理Windows套接字库
|
|
||||
rpc_winsock_cleanup(); |
|
||||
#endif |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
@ -1,41 +0,0 @@ |
|||||
/*
|
|
||||
* rpc_client_basic.c |
|
||||
* 最基础的RPC客户端实现 |
|
||||
*/ |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
#include <winsock2.h> |
|
||||
#include <ws2tcpip.h> |
|
||||
#pragma comment(lib, "ws2_32.lib") |
|
||||
#define close closesocket |
|
||||
#else |
|
||||
#include <unistd.h> |
|
||||
#include <sys/socket.h> |
|
||||
#include <netinet/in.h> |
|
||||
#include <arpa/inet.h> |
|
||||
#endif |
|
||||
|
|
||||
int main(int argc, char* argv[]) { |
|
||||
const char* server_host = "127.0.0.1"; |
|
||||
int server_port = 8080; |
|
||||
char file_path[256] = {0}; |
|
||||
|
|
||||
// 从命令行参数获取服务器信息
|
|
||||
if (argc >= 3) { |
|
||||
server_host = argv[1]; |
|
||||
server_port = atoi(argv[2]); |
|
||||
} |
|
||||
|
|
||||
printf("RPC客户端: 连接到 %s:%d\n", server_host, server_port); |
|
||||
printf("请输入文件路径: "); |
|
||||
fgets(file_path, sizeof(file_path), stdin); |
|
||||
file_path[strcspn(file_path, "\n")] = '\0'; |
|
||||
|
|
||||
printf("文件路径: %s\n", file_path); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
@ -1,103 +0,0 @@ |
|||||
/*
|
|
||||
* rpc_client_simple.c |
|
||||
* 简化版RPC客户端实现 |
|
||||
*/ |
|
||||
|
|
||||
#include "rpc_common.h" |
|
||||
#include "rpc_transport.h" |
|
||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
#include <winsock2.h> |
|
||||
#include <ws2tcpip.h> |
|
||||
#pragma comment(lib, "ws2_32.lib") |
|
||||
#else |
|
||||
#include <unistd.h> |
|
||||
#include <sys/socket.h> |
|
||||
#include <netinet/in.h> |
|
||||
#include <arpa/inet.h> |
|
||||
#endif |
|
||||
|
|
||||
int main(int argc, char* argv[]) { |
|
||||
const char* server_host = "127.0.0.1"; |
|
||||
uint16_t server_port = 8080; |
|
||||
char file_path[256] = {0}; |
|
||||
|
|
||||
// 从命令行参数获取服务器信息
|
|
||||
if (argc >= 3) { |
|
||||
server_host = argv[1]; |
|
||||
server_port = atoi(argv[2]); |
|
||||
} else { |
|
||||
printf("用法: rpc_client <server_host> <server_port>\n"); |
|
||||
printf("使用默认值: %s:%d\n", server_host, server_port); |
|
||||
} |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
WSADATA wsaData; |
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { |
|
||||
printf("初始化Winsock失败\n"); |
|
||||
return 1; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
printf("RPC客户端已启动\n"); |
|
||||
printf("连接到服务器 %s:%d...\n", server_host, server_port); |
|
||||
|
|
||||
// 创建TCP套接字
|
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0); |
|
||||
if (sockfd < 0) { |
|
||||
printf("创建套接字失败\n"); |
|
||||
#ifdef _WIN32 |
|
||||
WSACleanup(); |
|
||||
#endif |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
// 设置服务器地址
|
|
||||
struct sockaddr_in server_addr; |
|
||||
memset(&server_addr, 0, sizeof(server_addr)); |
|
||||
server_addr.sin_family = AF_INET; |
|
||||
server_addr.sin_port = htons(server_port); |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
inet_pton(AF_INET, server_host, &(server_addr.sin_addr)); |
|
||||
#else |
|
||||
inet_aton(server_host, &(server_addr.sin_addr)); |
|
||||
#endif |
|
||||
|
|
||||
// 连接到服务器
|
|
||||
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { |
|
||||
printf("连接到服务器失败\n"); |
|
||||
close(sockfd); |
|
||||
#ifdef _WIN32 |
|
||||
WSACleanup(); |
|
||||
#endif |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
printf("成功连接到服务器\n"); |
|
||||
|
|
||||
// 获取文件信息
|
|
||||
printf("请输入要操作的文件路径: "); |
|
||||
if (fgets(file_path, sizeof(file_path), stdin) != NULL) { |
|
||||
// 移除换行符
|
|
||||
file_path[strcspn(file_path, "\n")] = '\0'; |
|
||||
printf("准备发送文件 %s 的信息到服务器\n", file_path); |
|
||||
|
|
||||
// 简单发送文件名
|
|
||||
send(sockfd, file_path, strlen(file_path) + 1, 0); |
|
||||
printf("文件信息已发送\n"); |
|
||||
} |
|
||||
|
|
||||
// 关闭连接
|
|
||||
close(sockfd); |
|
||||
printf("已关闭与服务器的连接\n"); |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
WSACleanup(); |
|
||||
#endif |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
@ -1,120 +0,0 @@ |
|||||
/*
|
|
||||
* rpc_common.c |
|
||||
* 实现RPC框架的公共工具函数 |
|
||||
*/ |
|
||||
|
|
||||
#include "rpc_common.h" |
|
||||
|
|
||||
/*
|
|
||||
* 初始化RPC参数 |
|
||||
*/ |
|
||||
void rpc_init_param(rpc_param_t* param, rpc_param_type_t type) { |
|
||||
if (!param) return; |
|
||||
param->type = type; |
|
||||
switch (type) { |
|
||||
case RPC_TYPE_INT: |
|
||||
param->value.int_val = 0; |
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_FLOAT: |
|
||||
param->value.float_val = 0.0f; |
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_DOUBLE: |
|
||||
param->value.double_val = 0.0; |
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_STRING: |
|
||||
param->value.string_val = NULL; |
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_BOOL: |
|
||||
param->value.bool_val = false; |
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_VOID: |
|
||||
break; |
|
||||
|
|
||||
default: |
|
||||
break; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
* 释放参数数组中动态分配的资源 |
|
||||
*/ |
|
||||
void rpc_free_params(rpc_param_t* params, int count) { |
|
||||
if (!params || count <= 0) return; |
|
||||
|
|
||||
for (int i = 0; i < count; i++) { |
|
||||
if (params[i].type == RPC_TYPE_STRING && params[i].value.string_val) { |
|
||||
free((void*)params[i].value.string_val); |
|
||||
params[i].value.string_val = NULL; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* 释放请求消息中动态分配的资源 |
|
||||
*/ |
|
||||
void rpc_free_request(rpc_request_t* request) { |
|
||||
if (!request) return; |
|
||||
rpc_free_params(request->args, request->args_count); |
|
||||
request->args_count = 0; |
|
||||
request->func_name[0] = '\0'; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
* 释放响应消息中动态分配的资源 |
|
||||
*/ |
|
||||
|
|
||||
void rpc_free_response(rpc_response_t* response) { |
|
||||
if (!response) return; |
|
||||
|
|
||||
if (response->return_type == RPC_TYPE_STRING && response->return_value.string_val) { |
|
||||
free((void*)response->return_value.string_val); |
|
||||
response->return_value.string_val = NULL; |
|
||||
} |
|
||||
|
|
||||
response->result_code = 0; |
|
||||
response->return_type = RPC_TYPE_VOID; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
* 将错误码转换为字符串 |
|
||||
*/ |
|
||||
|
|
||||
const char* rpc_error_to_string(int error_code) { |
|
||||
switch (error_code) { |
|
||||
case RPC_SUCCESS: |
|
||||
return "Success"; |
|
||||
|
|
||||
case RPC_ERROR: |
|
||||
return "General error"; |
|
||||
|
|
||||
case RPC_NET_ERROR: |
|
||||
return "Network error"; |
|
||||
|
|
||||
case RPC_TIMEOUT: |
|
||||
return "Timeout error"; |
|
||||
|
|
||||
case RPC_INVALID_ARGS: |
|
||||
return "Invalid arguments"; |
|
||||
|
|
||||
case RPC_FUNC_NOT_FOUND: |
|
||||
return "Function not found"; |
|
||||
|
|
||||
default: |
|
||||
return "Unknown error"; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,381 +0,0 @@ |
|||||
/*
|
|
||||
|
|
||||
* rpc_message.c |
|
||||
|
|
||||
* 实现RPC消息的序列化和反序列化功能 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
#include "rpc_message.h" |
|
||||
|
|
||||
#include "rpc_transport.h" |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 序列化请求消息到缓冲区 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_serialize_request(const rpc_request_t* request, void* buffer, size_t buffer_size) { |
|
||||
|
|
||||
if (!request || !buffer || buffer_size < sizeof(rpc_request_t)) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制请求消息到缓冲区
|
|
||||
|
|
||||
memcpy(buffer, request, sizeof(rpc_request_t)); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 注意:这里简化了字符串参数的序列化,实际上可能需要更复杂的处理
|
|
||||
|
|
||||
// 在实际应用中,可能需要计算字符串的总长度并动态分配足够的缓冲区
|
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 反序列化缓冲区到请求消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_deserialize_request(const void* buffer, size_t buffer_size, rpc_request_t* request) { |
|
||||
|
|
||||
if (!buffer || !request || buffer_size < sizeof(rpc_request_t)) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 从缓冲区复制请求消息
|
|
||||
|
|
||||
memcpy(request, buffer, sizeof(rpc_request_t)); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 注意:这里简化了字符串参数的反序列化
|
|
||||
|
|
||||
// 在实际应用中,可能需要处理字符串的动态分配和复制
|
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 序列化响应消息到缓冲区 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_serialize_response(const rpc_response_t* response, void* buffer, size_t buffer_size) { |
|
||||
|
|
||||
if (!response || !buffer || buffer_size < sizeof(rpc_response_t)) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制响应消息到缓冲区
|
|
||||
|
|
||||
memcpy(buffer, response, sizeof(rpc_response_t)); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 注意:这里简化了字符串返回值的序列化
|
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 反序列化缓冲区到响应消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_deserialize_response(const void* buffer, size_t buffer_size, rpc_response_t* response) { |
|
||||
|
|
||||
if (!buffer || !response || buffer_size < sizeof(rpc_response_t)) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 从缓冲区复制响应消息
|
|
||||
|
|
||||
memcpy(response, buffer, sizeof(rpc_response_t)); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 注意:这里简化了字符串返回值的反序列化
|
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 发送请求消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_send_request(rpc_transport_t* transport, const rpc_request_t* request) { |
|
||||
|
|
||||
if (!transport || !request) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
uint8_t buffer[MAX_MESSAGE_SIZE]; |
|
||||
|
|
||||
rpc_message_t message; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 设置消息头部
|
|
||||
|
|
||||
message.header.type = RPC_MESSAGE_REQUEST; |
|
||||
|
|
||||
message.header.payload_size = sizeof(rpc_request_t); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制请求到消息负载
|
|
||||
|
|
||||
message.payload.request = *request; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 序列化整个消息
|
|
||||
|
|
||||
size_t message_size = sizeof(rpc_message_header_t) + message.header.payload_size; |
|
||||
|
|
||||
if (message_size > MAX_MESSAGE_SIZE) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
memcpy(buffer, &message, message_size); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 发送消息
|
|
||||
|
|
||||
return rpc_transport_send(transport, buffer, message_size); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 接收请求消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_recv_request(rpc_transport_t* transport, rpc_request_t* request) { |
|
||||
|
|
||||
if (!transport || !request) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
uint8_t buffer[MAX_MESSAGE_SIZE]; |
|
||||
|
|
||||
rpc_message_header_t header; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 接收消息头部
|
|
||||
|
|
||||
if (rpc_transport_recv(transport, &header, sizeof(rpc_message_header_t)) != RPC_SUCCESS) { |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 检查消息类型和大小
|
|
||||
|
|
||||
if (header.type != RPC_MESSAGE_REQUEST || header.payload_size > MAX_MESSAGE_SIZE - sizeof(rpc_message_header_t)) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 接收消息负载
|
|
||||
|
|
||||
if (rpc_transport_recv(transport, request, header.payload_size) != RPC_SUCCESS) { |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 发送响应消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_send_response(rpc_transport_t* transport, const rpc_response_t* response) { |
|
||||
|
|
||||
if (!transport || !response) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
uint8_t buffer[MAX_MESSAGE_SIZE]; |
|
||||
|
|
||||
rpc_message_t message; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 设置消息头部
|
|
||||
|
|
||||
message.header.type = RPC_MESSAGE_RESPONSE; |
|
||||
|
|
||||
message.header.payload_size = sizeof(rpc_response_t); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制响应到消息负载
|
|
||||
|
|
||||
message.payload.response = *response; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 序列化整个消息
|
|
||||
|
|
||||
size_t message_size = sizeof(rpc_message_header_t) + message.header.payload_size; |
|
||||
|
|
||||
if (message_size > MAX_MESSAGE_SIZE) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
memcpy(buffer, &message, message_size); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 发送消息
|
|
||||
|
|
||||
return rpc_transport_send(transport, buffer, message_size); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 接收响应消息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_recv_response(rpc_transport_t* transport, rpc_response_t* response) { |
|
||||
|
|
||||
if (!transport || !response) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
uint8_t buffer[MAX_MESSAGE_SIZE]; |
|
||||
|
|
||||
rpc_message_header_t header; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 接收消息头部
|
|
||||
|
|
||||
if (rpc_transport_recv(transport, &header, sizeof(rpc_message_header_t)) != RPC_SUCCESS) { |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 检查消息类型和大小
|
|
||||
|
|
||||
if (header.type != RPC_MESSAGE_RESPONSE || header.payload_size > MAX_MESSAGE_SIZE - sizeof(rpc_message_header_t)) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 接收消息负载
|
|
||||
|
|
||||
if (rpc_transport_recv(transport, response, header.payload_size) != RPC_SUCCESS) { |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
@ -1,591 +0,0 @@ |
|||||
/*
|
|
||||
|
|
||||
* rpc_server.c |
|
||||
|
|
||||
* RPC服务器实现,处理客户端连接和执行远程函数调用 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
#include "rpc_common.h" |
|
||||
|
|
||||
#include "rpc_transport.h" |
|
||||
|
|
||||
#include "rpc_message.h" |
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
#include <windows.h> |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
#include <pthread.h> |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
|
|
||||
/* 函数处理函数类型定义 */ |
|
||||
|
|
||||
typedef int (*rpc_handler_func_t)(rpc_param_t* params, int args_count, rpc_param_t* return_value); |
|
||||
|
|
||||
|
|
||||
|
|
||||
/* 函数处理器结构 */ |
|
||||
|
|
||||
typedef struct { |
|
||||
|
|
||||
char func_name[MAX_FUNC_NAME_LEN]; |
|
||||
|
|
||||
rpc_handler_func_t handler; |
|
||||
|
|
||||
rpc_param_type_t return_type; |
|
||||
|
|
||||
rpc_param_type_t param_types[MAX_ARGS_COUNT]; |
|
||||
|
|
||||
int param_count; |
|
||||
|
|
||||
} rpc_handler_t; |
|
||||
|
|
||||
|
|
||||
|
|
||||
/* 函数处理器表 */ |
|
||||
|
|
||||
static rpc_handler_t handlers[MAX_FUNC_NAME_LEN]; |
|
||||
|
|
||||
static int handler_count = 0; |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 注册远程函数 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_register_function(const char* func_name, rpc_handler_func_t handler, |
|
||||
|
|
||||
rpc_param_type_t return_type, |
|
||||
|
|
||||
rpc_param_type_t* param_types, int param_count) { |
|
||||
|
|
||||
if (!func_name || !handler || param_count < 0 || param_count > MAX_ARGS_COUNT) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
if (handler_count >= MAX_FUNC_NAME_LEN) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 检查函数名是否已存在
|
|
||||
|
|
||||
for (int i = 0; i < handler_count; i++) { |
|
||||
|
|
||||
if (strcmp(handlers[i].func_name, func_name) == 0) { |
|
||||
|
|
||||
return RPC_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 添加新的函数处理器
|
|
||||
|
|
||||
strncpy(handlers[handler_count].func_name, func_name, MAX_FUNC_NAME_LEN - 1); |
|
||||
|
|
||||
handlers[handler_count].func_name[MAX_FUNC_NAME_LEN - 1] = '\0'; |
|
||||
|
|
||||
handlers[handler_count].handler = handler; |
|
||||
|
|
||||
handlers[handler_count].return_type = return_type; |
|
||||
|
|
||||
handlers[handler_count].param_count = param_count; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制参数类型
|
|
||||
|
|
||||
if (param_count > 0 && param_types) { |
|
||||
|
|
||||
memcpy(handlers[handler_count].param_types, param_types, |
|
||||
|
|
||||
sizeof(rpc_param_type_t) * param_count); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
handler_count++; |
|
||||
|
|
||||
printf("Registered function: %s\n", func_name); |
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 查找函数处理器 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
rpc_handler_t* rpc_find_handler(const char* func_name) { |
|
||||
|
|
||||
for (int i = 0; i < handler_count; i++) { |
|
||||
|
|
||||
if (strcmp(handlers[i].func_name, func_name) == 0) { |
|
||||
|
|
||||
return &handlers[i]; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 处理客户端请求 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
DWORD WINAPI handle_client(LPVOID arg) { |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
void* handle_client(void* arg) { |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
rpc_transport_t* transport = (rpc_transport_t*)arg; |
|
||||
|
|
||||
rpc_request_t request; |
|
||||
|
|
||||
rpc_response_t response; |
|
||||
|
|
||||
int ret; |
|
||||
|
|
||||
|
|
||||
|
|
||||
while (1) { |
|
||||
|
|
||||
// 接收请求
|
|
||||
|
|
||||
ret = rpc_recv_request(transport, &request); |
|
||||
|
|
||||
if (ret != RPC_SUCCESS) { |
|
||||
|
|
||||
printf("Failed to receive request: %s\n", rpc_error_to_string(ret)); |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
printf("Received request: %s with %d arguments\n", request.func_name, request.args_count); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 查找函数处理器
|
|
||||
|
|
||||
rpc_handler_t* handler = rpc_find_handler(request.func_name); |
|
||||
|
|
||||
if (!handler) { |
|
||||
|
|
||||
printf("Function not found: %s\n", request.func_name); |
|
||||
|
|
||||
response.result_code = RPC_FUNC_NOT_FOUND; |
|
||||
|
|
||||
response.return_type = RPC_TYPE_VOID; |
|
||||
|
|
||||
rpc_send_response(transport, &response); |
|
||||
|
|
||||
rpc_free_request(&request); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 检查参数数量
|
|
||||
|
|
||||
if (request.args_count != handler->param_count) { |
|
||||
|
|
||||
printf("Invalid argument count for %s\n", request.func_name); |
|
||||
|
|
||||
response.result_code = RPC_INVALID_ARGS; |
|
||||
|
|
||||
response.return_type = RPC_TYPE_VOID; |
|
||||
|
|
||||
rpc_send_response(transport, &response); |
|
||||
|
|
||||
rpc_free_request(&request); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 执行函数
|
|
||||
|
|
||||
rpc_param_t return_value; |
|
||||
|
|
||||
rpc_init_param(&return_value, handler->return_type); |
|
||||
|
|
||||
|
|
||||
|
|
||||
ret = handler->handler(request.args, request.args_count, &return_value); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 设置响应
|
|
||||
|
|
||||
response.result_code = ret; |
|
||||
|
|
||||
response.return_type = handler->return_type; |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 复制返回值
|
|
||||
|
|
||||
switch (handler->return_type) { |
|
||||
|
|
||||
case RPC_TYPE_INT: |
|
||||
|
|
||||
response.return_value.int_val = return_value.value.int_val; |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_FLOAT: |
|
||||
|
|
||||
response.return_value.float_val = return_value.value.float_val; |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_DOUBLE: |
|
||||
|
|
||||
response.return_value.double_val = return_value.value.double_val; |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_STRING: |
|
||||
|
|
||||
// 注意:这里需要复制字符串,避免内存问题
|
|
||||
|
|
||||
response.return_value.string_val = strdup(return_value.value.string_val); |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_BOOL: |
|
||||
|
|
||||
response.return_value.bool_val = return_value.value.bool_val; |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
case RPC_TYPE_VOID: |
|
||||
|
|
||||
default: |
|
||||
|
|
||||
break; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 发送响应
|
|
||||
|
|
||||
rpc_send_response(transport, &response); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 释放资源
|
|
||||
|
|
||||
rpc_free_request(&request); |
|
||||
|
|
||||
if (handler->return_type == RPC_TYPE_STRING && return_value.value.string_val) { |
|
||||
|
|
||||
free((void*)return_value.value.string_val); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
if (response.return_type == RPC_TYPE_STRING && response.return_value.string_val) { |
|
||||
|
|
||||
free((void*)response.return_value.string_val); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 关闭连接
|
|
||||
|
|
||||
rpc_transport_close(transport); |
|
||||
|
|
||||
free(transport); |
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
return 0; |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
return NULL; |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 示例函数:加法 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int add_handler(rpc_param_t* params, int args_count, rpc_param_t* return_value) { |
|
||||
|
|
||||
if (args_count < 2 || params[0].type != RPC_TYPE_INT || params[1].type != RPC_TYPE_INT) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
int a = params[0].value.int_val; |
|
||||
|
|
||||
int b = params[1].value.int_val; |
|
||||
|
|
||||
|
|
||||
|
|
||||
return_value->value.int_val = a + b; |
|
||||
|
|
||||
|
|
||||
|
|
||||
printf("Executed add(%d, %d) = %d\n", a, b, return_value->value.int_val); |
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 示例函数:获取服务器信息 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int get_server_info_handler(rpc_param_t* params, int args_count, rpc_param_t* return_value) { |
|
||||
|
|
||||
const char* info = "RPC Server v1.0"; |
|
||||
|
|
||||
return_value->value.string_val = strdup(info); |
|
||||
|
|
||||
|
|
||||
|
|
||||
printf("Executed get_server_info()\n"); |
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 主函数 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int main(int argc, char* argv[]) { |
|
||||
|
|
||||
rpc_server_t server; |
|
||||
|
|
||||
int port = 8080; |
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
// 初始化Windows套接字库
|
|
||||
|
|
||||
if (rpc_winsock_init() != RPC_SUCCESS) { |
|
||||
|
|
||||
printf("Failed to initialize Winsock\n"); |
|
||||
|
|
||||
return 1; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 注册示例函数
|
|
||||
|
|
||||
rpc_param_type_t add_params[] = {RPC_TYPE_INT, RPC_TYPE_INT}; |
|
||||
|
|
||||
rpc_register_function("add", add_handler, RPC_TYPE_INT, add_params, 2); |
|
||||
|
|
||||
rpc_register_function("get_server_info", get_server_info_handler, RPC_TYPE_STRING, NULL, 0); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 初始化服务器
|
|
||||
|
|
||||
if (rpc_server_init(&server, "0.0.0.0", port, 5) != RPC_SUCCESS) { |
|
||||
|
|
||||
printf("Failed to initialize server\n"); |
|
||||
|
|
||||
return 1; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
printf("RPC Server listening on port %d\n", port); |
|
||||
|
|
||||
printf("Waiting for client connections...\n"); |
|
||||
|
|
||||
|
|
||||
|
|
||||
while (1) { |
|
||||
|
|
||||
// 接受客户端连接
|
|
||||
|
|
||||
rpc_transport_t* client_transport = (rpc_transport_t*)malloc(sizeof(rpc_transport_t)); |
|
||||
|
|
||||
if (!client_transport) { |
|
||||
|
|
||||
printf("Failed to allocate memory\n"); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
if (rpc_server_accept(&server, client_transport) != RPC_SUCCESS) { |
|
||||
|
|
||||
free(client_transport); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 创建线程处理客户端请求
|
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
HANDLE thread_handle = CreateThread( |
|
||||
|
|
||||
NULL, // 默认安全属性
|
|
||||
|
|
||||
0, // 默认堆栈大小
|
|
||||
|
|
||||
handle_client, // 线程函数
|
|
||||
|
|
||||
client_transport, // 线程参数
|
|
||||
|
|
||||
0, // 默认创建标志
|
|
||||
|
|
||||
NULL // 线程ID(不需要)
|
|
||||
|
|
||||
); |
|
||||
|
|
||||
if (thread_handle == NULL) { |
|
||||
|
|
||||
fprintf(stderr, "CreateThread failed with error code: %d\n", GetLastError()); |
|
||||
|
|
||||
rpc_transport_close(client_transport); |
|
||||
|
|
||||
free(client_transport); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 关闭线程句柄但不终止线程,让线程自动结束
|
|
||||
|
|
||||
CloseHandle(thread_handle); |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
pthread_t thread_id; |
|
||||
|
|
||||
if (pthread_create(&thread_id, NULL, handle_client, client_transport) != 0) { |
|
||||
|
|
||||
perror("pthread_create failed"); |
|
||||
|
|
||||
rpc_transport_close(client_transport); |
|
||||
|
|
||||
free(client_transport); |
|
||||
|
|
||||
continue; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 分离线程,自动回收资源
|
|
||||
|
|
||||
pthread_detach(thread_id); |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 关闭服务器
|
|
||||
|
|
||||
rpc_server_close(&server); |
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
// 清理Windows套接字库
|
|
||||
|
|
||||
rpc_winsock_cleanup(); |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
|
|
||||
return 0; |
|
||||
|
|
||||
} |
|
||||
@ -1,415 +0,0 @@ |
|||||
/*
|
|
||||
* rpc_transport.c |
|
||||
* 实现RPC传输层的功能,处理网络通信 |
|
||||
*/ |
|
||||
|
|
||||
#include "rpc_transport.h" |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
/*
|
|
||||
* 初始化Windows套接字库 |
|
||||
*/ |
|
||||
int rpc_winsock_init() { |
|
||||
WSADATA wsaData; |
|
||||
int result = WSAStartup(MAKEWORD(2, 2), &wsaData); |
|
||||
if (result != 0) { |
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", result); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
return RPC_SUCCESS; |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* 清理Windows套接字库 |
|
||||
*/ |
|
||||
void rpc_winsock_cleanup() { |
|
||||
WSACleanup(); |
|
||||
} |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
/*
|
|
||||
* Windows平台的错误打印函数 |
|
||||
*/ |
|
||||
static void print_windows_error(const char* message) { |
|
||||
int error_code = WSAGetLastError(); |
|
||||
char* error_text = NULL; |
|
||||
FormatMessageA( |
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
|
||||
NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
|
||||
(LPSTR)&error_text, 0, NULL); |
|
||||
if (error_text) { |
|
||||
fprintf(stderr, "%s: %s\n", message, error_text); |
|
||||
LocalFree(error_text); |
|
||||
} else { |
|
||||
fprintf(stderr, "%s: Error code %d\n", message, error_code); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#define PRINT_ERROR(msg) print_windows_error(msg) |
|
||||
#else |
|
||||
/*
|
|
||||
* Linux/Unix平台的错误打印函数 |
|
||||
*/ |
|
||||
#define PRINT_ERROR(msg) perror(msg) |
|
||||
#endif |
|
||||
|
|
||||
/*
|
|
||||
* 初始化RPC服务器 |
|
||||
*/ |
|
||||
int rpc_server_init(rpc_server_t* server, const char* host, uint16_t port, int backlog) { |
|
||||
// 初始化Windows套接字库(如果需要)
|
|
||||
if (rpc_winsock_init() != RPC_SUCCESS) { |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 创建套接字
|
|
||||
server->server_fd = socket(AF_INET, SOCK_STREAM, 0); |
|
||||
if (server->server_fd == INVALID_SOCKET_VALUE) { |
|
||||
PRINT_ERROR("socket creation failed"); |
|
||||
rpc_winsock_cleanup(); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 设置套接字选项,允许地址重用
|
|
||||
int opt = 1; |
|
||||
#ifdef _WIN32 |
|
||||
// Windows不支持SO_REUSEPORT
|
|
||||
if (setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, |
|
||||
&opt, sizeof(opt)) != 0) { |
|
||||
#else |
|
||||
// Linux/Unix支持SO_REUSEPORT
|
|
||||
if (setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, |
|
||||
&opt, sizeof(opt)) != 0) { |
|
||||
#endif |
|
||||
PRINT_ERROR("setsockopt failed"); |
|
||||
CLOSE_SOCKET(server->server_fd); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 设置服务器地址结构(使用局部变量,避免访问server->address)
|
|
||||
struct sockaddr_in addr; |
|
||||
memset(&addr, 0, sizeof(addr)); |
|
||||
addr.sin_family = AF_INET; |
|
||||
addr.sin_addr.s_addr = inet_addr(host); |
|
||||
addr.sin_port = htons(port); |
|
||||
|
|
||||
// 绑定地址到套接字
|
|
||||
if (bind(server->server_fd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) { |
|
||||
PRINT_ERROR("bind failed"); |
|
||||
CLOSE_SOCKET(server->server_fd); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
// 开始监听连接
|
|
||||
if (listen(server->server_fd, backlog) != 0) { |
|
||||
PRINT_ERROR("listen failed"); |
|
||||
CLOSE_SOCKET(server->server_fd); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
printf("RPC Server started on %s:%d\n", host, port); |
|
||||
return RPC_SUCCESS; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 服务器接受客户端连接 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_server_accept(rpc_server_t* server, rpc_transport_t* transport) { |
|
||||
|
|
||||
if (!server || !transport) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
socklen_t addrlen = sizeof(transport->address); |
|
||||
|
|
||||
transport->socket_fd = accept(server->server_fd, (struct sockaddr*)&transport->address, &addrlen); |
|
||||
|
|
||||
if (transport->socket_fd == INVALID_SOCKET_VALUE) { |
|
||||
|
|
||||
PRINT_ERROR("accept failed"); |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
printf("Client connected: %s:%d\n", |
|
||||
|
|
||||
inet_ntoa(transport->address.sin_addr), |
|
||||
|
|
||||
ntohs(transport->address.sin_port)); |
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 关闭RPC服务器 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
void rpc_server_close(rpc_server_t* server) { |
|
||||
|
|
||||
if (!server || server->server_fd == INVALID_SOCKET_VALUE) { |
|
||||
|
|
||||
return; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
CLOSE_SOCKET(server->server_fd); |
|
||||
|
|
||||
server->server_fd = INVALID_SOCKET_VALUE; |
|
||||
|
|
||||
printf("RPC Server closed\n"); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 初始化RPC客户端传输 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_client_init(rpc_transport_t* transport, const char* server_host, uint16_t server_port) { |
|
||||
|
|
||||
if (!transport || !server_host) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 创建套接字
|
|
||||
|
|
||||
transport->socket_fd = socket(AF_INET, SOCK_STREAM, 0); |
|
||||
|
|
||||
if (transport->socket_fd == INVALID_SOCKET_VALUE) { |
|
||||
|
|
||||
PRINT_ERROR("socket creation failed"); |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 设置服务器地址结构
|
|
||||
|
|
||||
memset(&transport->address, 0, sizeof(transport->address)); |
|
||||
|
|
||||
transport->address.sin_family = AF_INET; |
|
||||
|
|
||||
transport->address.sin_port = htons(server_port); |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 将主机名转换为IP地址
|
|
||||
|
|
||||
if (inet_pton(AF_INET, server_host, &transport->address.sin_addr) <= 0) { |
|
||||
|
|
||||
PRINT_ERROR("invalid address"); |
|
||||
|
|
||||
CLOSE_SOCKET(transport->socket_fd); |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 连接到服务器
|
|
||||
|
|
||||
const struct sockaddr* conn_addr_ptr = (const struct sockaddr*)&transport->address; |
|
||||
int conn_addr_len = sizeof(transport->address); |
|
||||
#ifdef _WIN32 |
|
||||
if (connect(transport->socket_fd, conn_addr_ptr, conn_addr_len) != 0) { |
|
||||
#else |
|
||||
if (connect(transport->socket_fd, conn_addr_ptr, conn_addr_len) != 0) { |
|
||||
#endif |
|
||||
PRINT_ERROR("connection failed"); |
|
||||
CLOSE_SOCKET(transport->socket_fd); |
|
||||
return RPC_NET_ERROR; |
|
||||
} |
|
||||
|
|
||||
printf("Connected to server %s:%d\n", server_host, server_port); |
|
||||
return RPC_SUCCESS; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 通过传输层发送数据 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_transport_send(rpc_transport_t* transport, const void* data, size_t data_size) { |
|
||||
|
|
||||
if (!transport || !data || data_size == 0) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 发送所有数据
|
|
||||
|
|
||||
size_t sent_bytes = 0; |
|
||||
|
|
||||
while (sent_bytes < data_size) { |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
int bytes = send(transport->socket_fd, (const char*)data + sent_bytes, ( |
|
||||
|
|
||||
#ifdef _WIN64 |
|
||||
|
|
||||
int |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
int |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
)(data_size - sent_bytes), 0); |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
ssize_t bytes = send(transport->socket_fd, (const char*)data + sent_bytes, data_size - sent_bytes, 0); |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
if (bytes <= 0) { |
|
||||
|
|
||||
PRINT_ERROR("send failed"); |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
sent_bytes += bytes; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 通过传输层接收数据 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
int rpc_transport_recv(rpc_transport_t* transport, void* buffer, size_t buffer_size) { |
|
||||
|
|
||||
if (!transport || !buffer || buffer_size == 0) { |
|
||||
|
|
||||
return RPC_INVALID_ARGS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 接收所有数据
|
|
||||
|
|
||||
size_t recv_bytes = 0; |
|
||||
|
|
||||
while (recv_bytes < buffer_size) { |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
int bytes = recv(transport->socket_fd, (char*)buffer + recv_bytes, ( |
|
||||
|
|
||||
#ifdef _WIN64 |
|
||||
|
|
||||
int |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
int |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
)(buffer_size - recv_bytes), 0); |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
ssize_t bytes = recv(transport->socket_fd, (char*)buffer + recv_bytes, buffer_size - recv_bytes, 0); |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
if (bytes < 0) { |
|
||||
|
|
||||
PRINT_ERROR("recv failed"); |
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} else if (bytes == 0) { |
|
||||
|
|
||||
// 连接关闭
|
|
||||
|
|
||||
return RPC_NET_ERROR; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
recv_bytes += bytes; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
return RPC_SUCCESS; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*
|
|
||||
|
|
||||
* 关闭传输连接 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
void rpc_transport_close(rpc_transport_t* transport) { |
|
||||
|
|
||||
if (!transport || transport->socket_fd == INVALID_SOCKET_VALUE) { |
|
||||
|
|
||||
return; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
CLOSE_SOCKET(transport->socket_fd); |
|
||||
|
|
||||
transport->socket_fd = INVALID_SOCKET_VALUE; |
|
||||
|
|
||||
} |
|
||||
Loading…
Reference in new issue