From 820805dd109c865129be214ccaee7bd6937cfd41 Mon Sep 17 00:00:00 2001 From: xc Date: Sun, 28 Sep 2025 16:47:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=96=87=E4=BB=B6=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E4=B8=BAlinux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scalib/.gitignore | 1 + scalib/README.md | 330 +++++++++--------- scalib/build_windows.bat | 120 +++---- scalib/convert_encoding.py | 108 ++++++ scalib/include/rpc_message.h | 116 +++---- scalib/include/rpc_transport.h | 152 ++++----- scalib/src/CMakeLists.txt | 108 +++--- scalib/src/rpc_common.c | 192 +++++------ scalib/src/rpc_message.c | 380 ++++++++++----------- scalib/src/rpc_server.c | 590 ++++++++++++++++----------------- scalib/src/rpc_transport.c | 516 ++++++++++++++-------------- scalib/test_compile.cmd | 64 ++-- 12 files changed, 1393 insertions(+), 1284 deletions(-) create mode 100644 scalib/convert_encoding.py diff --git a/scalib/.gitignore b/scalib/.gitignore index 762523a..eb5b8b0 100644 --- a/scalib/.gitignore +++ b/scalib/.gitignore @@ -14,6 +14,7 @@ install/ *.o *.obj + # 临时文件 *.tmp *.temp diff --git a/scalib/README.md b/scalib/README.md index 971856e..baa2e30 100644 --- a/scalib/README.md +++ b/scalib/README.md @@ -1,166 +1,166 @@ -# RPC Demo Project - -这是一个用C语言实现的简单RPC(Remote Procedure Call)框架,可以在Linux环境下运行。这个框架允许客户端程序远程调用服务器上的函数,就像调用本地函数一样。 - -## 项目结构 - -``` -├── include/ # 头文件目录 -│ ├── rpc_common.h # 公共定义和工具函数 -│ ├── rpc_transport.h # 网络传输层接口 -│ └── rpc_message.h # 消息序列化和反序列化 -├── src/ # 源代码目录 -│ ├── rpc_common.c # 公共函数实现 -│ ├── rpc_transport.c # 传输层实现 -│ ├── rpc_message.c # 消息处理实现 -│ ├── rpc_server.c # RPC服务器实现 -│ ├── rpc_client.c # RPC客户端实现 -│ └── CMakeLists.txt # 源代码CMake配置 -├── cmake/ # CMake模块目录 -├── CMakeLists.txt # 主CMake配置文件 -└── README.md # 项目说明文档 -``` - -## 功能特性 - -- 支持基本数据类型的远程函数调用(int、float、double、string、bool、void) -- 支持多参数和返回值 -- 基于TCP/IP协议的网络通信 -- 多线程服务器设计,支持并发请求 -- 使用CMake构建系统 - -## 编译和构建 - -### Linux 平台 - -在Linux环境下,使用以下命令编译项目: - -```bash -# 创建构建目录 -mkdir build && cd build - -# 运行CMake配置 -cmake .. - -# 编译项目 -make - -# 安装(可选) -make install -``` - -### Windows 平台 - -1. 确保已安装 CMake(3.10 或更高版本)和 Visual Studio 2017 或更高版本 -2. 使用提供的构建脚本(以管理员身份运行命令提示符): - -```batch -build_windows.bat -``` - -3. 构建完成后,可执行文件将位于 `install\bin\` 目录下 - -或者手动构建: - -```batch -mkdir build_windows -cd build_windows -cmake .. -G "Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=..\install -cmake --build . --config Release -cmake --build . --config Release --target install -``` - -### 运行示例 - -无论是在Linux还是Windows平台上,运行示例的方式相同: - -1. 首先启动服务器: - ```bash - cd install/bin - ./rpc_server # Linux - rpc_server.exe # Windows - ``` - -2. 在另一个终端启动客户端: - ```bash - cd install/bin - ./rpc_client # Linux - rpc_client.exe # Windows - ``` - -3. 客户端将连接到服务器并执行两个示例操作: - - 调用远程加法函数 `add(10, 20)` - - 调用远程函数获取服务器信息 `get_server_info()` - -4. 查看终端输出以确认操作是否成功完成 - -## 使用示例 - -### 启动服务器 - -```bash -./bin/rpc_server -``` - -服务器将在8080端口上监听客户端连接。 - -### 运行客户端 - -```bash -./bin/rpc_client -``` - -客户端将连接到服务器并调用两个示例函数: -- `add(10, 20)` - 远程加法运算 -- `get_server_info()` - 获取服务器信息 - -## 自定义扩展 - -### 注册新的远程函数 - -要在服务器端添加新的远程函数,您需要: - -1. 实现函数处理器 -2. 使用`rpc_register_function`注册函数 - -示例: - -```c -// 函数实现 -example_handler(rpc_param_t* params, int args_count, rpc_param_t* return_value) { - // 函数逻辑 - return RPC_SUCCESS; -} - -// 注册函数 -rpc_param_type_t example_params[] = {RPC_TYPE_INT, RPC_TYPE_STRING}; -rpc_register_function("example_func", example_handler, RPC_TYPE_STRING, example_params, 2); -``` - -### 客户端调用新函数 - -在客户端调用新注册的函数: - -```c -rpc_param_t params[2]; -rpc_param_t return_value; - -// 设置参数 -rpc_init_param(¶ms[0], RPC_TYPE_INT); -params[0].value.int_val = 123; - -rpc_init_param(¶ms[1], RPC_TYPE_STRING); -params[1].value.string_val = "example string"; - -// 设置返回值 -rpc_init_param(&return_value, RPC_TYPE_STRING); - -// 调用远程函数 -int ret = rpc_call(client, "example_func", params, 2, &return_value); -``` - -## 注意事项 - -- 本项目是一个教学示例,可能不适合在生产环境中使用 -- 当前实现中,字符串参数和返回值的处理使用了简单的内存管理策略,在实际应用中可能需要更复杂的处理 +# RPC Demo Project + +这是一个用C语言实现的简单RPC(Remote Procedure Call)框架,可以在Linux环境下运行。这个框架允许客户端程序远程调用服务器上的函数,就像调用本地函数一样。 + +## 项目结构 + +``` +├── include/ # 头文件目录 +│ ├── rpc_common.h # 公共定义和工具函数 +│ ├── rpc_transport.h # 网络传输层接口 +│ └── rpc_message.h # 消息序列化和反序列化 +├── src/ # 源代码目录 +│ ├── rpc_common.c # 公共函数实现 +│ ├── rpc_transport.c # 传输层实现 +│ ├── rpc_message.c # 消息处理实现 +│ ├── rpc_server.c # RPC服务器实现 +│ ├── rpc_client.c # RPC客户端实现 +│ └── CMakeLists.txt # 源代码CMake配置 +├── cmake/ # CMake模块目录 +├── CMakeLists.txt # 主CMake配置文件 +└── README.md # 项目说明文档 +``` + +## 功能特性 + +- 支持基本数据类型的远程函数调用(int、float、double、string、bool、void) +- 支持多参数和返回值 +- 基于TCP/IP协议的网络通信 +- 多线程服务器设计,支持并发请求 +- 使用CMake构建系统 + +## 编译和构建 + +### Linux 平台 + +在Linux环境下,使用以下命令编译项目: + +```bash +# 创建构建目录 +mkdir build && cd build + +# 运行CMake配置 +cmake .. + +# 编译项目 +make + +# 安装(可选) +make install +``` + +### Windows 平台 + +1. 确保已安装 CMake(3.10 或更高版本)和 Visual Studio 2017 或更高版本 +2. 使用提供的构建脚本(以管理员身份运行命令提示符): + +```batch +build_windows.bat +``` + +3. 构建完成后,可执行文件将位于 `install\bin\` 目录下 + +或者手动构建: + +```batch +mkdir build_windows +cd build_windows +cmake .. -G "Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=..\install +cmake --build . --config Release +cmake --build . --config Release --target install +``` + +### 运行示例 + +无论是在Linux还是Windows平台上,运行示例的方式相同: + +1. 首先启动服务器: + ```bash + cd install/bin + ./rpc_server # Linux + rpc_server.exe # Windows + ``` + +2. 在另一个终端启动客户端: + ```bash + cd install/bin + ./rpc_client # Linux + rpc_client.exe # Windows + ``` + +3. 客户端将连接到服务器并执行两个示例操作: + - 调用远程加法函数 `add(10, 20)` + - 调用远程函数获取服务器信息 `get_server_info()` + +4. 查看终端输出以确认操作是否成功完成 + +## 使用示例 + +### 启动服务器 + +```bash +./bin/rpc_server +``` + +服务器将在8080端口上监听客户端连接。 + +### 运行客户端 + +```bash +./bin/rpc_client +``` + +客户端将连接到服务器并调用两个示例函数: +- `add(10, 20)` - 远程加法运算 +- `get_server_info()` - 获取服务器信息 + +## 自定义扩展 + +### 注册新的远程函数 + +要在服务器端添加新的远程函数,您需要: + +1. 实现函数处理器 +2. 使用`rpc_register_function`注册函数 + +示例: + +```c +// 函数实现 +example_handler(rpc_param_t* params, int args_count, rpc_param_t* return_value) { + // 函数逻辑 + return RPC_SUCCESS; +} + +// 注册函数 +rpc_param_type_t example_params[] = {RPC_TYPE_INT, RPC_TYPE_STRING}; +rpc_register_function("example_func", example_handler, RPC_TYPE_STRING, example_params, 2); +``` + +### 客户端调用新函数 + +在客户端调用新注册的函数: + +```c +rpc_param_t params[2]; +rpc_param_t return_value; + +// 设置参数 +rpc_init_param(¶ms[0], RPC_TYPE_INT); +params[0].value.int_val = 123; + +rpc_init_param(¶ms[1], RPC_TYPE_STRING); +params[1].value.string_val = "example string"; + +// 设置返回值 +rpc_init_param(&return_value, RPC_TYPE_STRING); + +// 调用远程函数 +int ret = rpc_call(client, "example_func", params, 2, &return_value); +``` + +## 注意事项 + +- 本项目是一个教学示例,可能不适合在生产环境中使用 +- 当前实现中,字符串参数和返回值的处理使用了简单的内存管理策略,在实际应用中可能需要更复杂的处理 - 错误处理机制相对简单,实际应用中可能需要更完善的错误处理 \ No newline at end of file diff --git a/scalib/build_windows.bat b/scalib/build_windows.bat index 1c87cb4..35e671a 100644 --- a/scalib/build_windows.bat +++ b/scalib/build_windows.bat @@ -1,61 +1,61 @@ -@echo off - -REM Windows平台构建脚本 - -REM 配置参数 -set BUILD_DIR=build_windows -set CMAKE_GENERATOR="Visual Studio 17 2022" -set INSTALL_PREFIX=install - -REM 检查命令行参数 -:parse_args -if "%1"=="--clean" ( - echo Cleaning build directory... - if exist %BUILD_DIR% rmdir /s /q %BUILD_DIR% - if exist %INSTALL_PREFIX% rmdir /s /q %INSTALL_PREFIX% - shift -) - -REM 创建构建目录 -if not exist %BUILD_DIR% mkdir %BUILD_DIR% - -REM 运行CMake配置 -pushd %BUILD_DIR% -echo Running CMake configuration... -cmake .. -G %CMAKE_GENERATOR% -DCMAKE_INSTALL_PREFIX=../%INSTALL_PREFIX% -if %ERRORLEVEL% neq 0 ( - echo CMake configuration failed! - popd - exit /b 1 -) - -REM 构建项目 -echo Building project... -cmake --build . --config Release -if %ERRORLEVEL% neq 0 ( - echo Build failed! - popd - exit /b 1 -) - -REM 安装项目 -echo Installing project... -cmake --build . --config Release --target install -if %ERRORLEVEL% neq 0 ( - echo Installation failed! - popd - exit /b 1 -) - -popd - -echo Build completed successfully! -echo Server executable: %INSTALL_PREFIX%\bin\rpc_server.exeecho Client executable: %INSTALL_PREFIX%\bin\rpc_client.exe -echo -echo To run the server: -cd %INSTALL_PREFIX%\bin -echo rpc_server.exe - -echo -echo Then in another terminal: +@echo off + +REM Windows平台构建脚本 + +REM 配置参数 +set BUILD_DIR=build_windows +set CMAKE_GENERATOR="Visual Studio 17 2022" +set INSTALL_PREFIX=install + +REM 检查命令行参数 +:parse_args +if "%1"=="--clean" ( + echo Cleaning build directory... + if exist %BUILD_DIR% rmdir /s /q %BUILD_DIR% + if exist %INSTALL_PREFIX% rmdir /s /q %INSTALL_PREFIX% + shift +) + +REM 创建构建目录 +if not exist %BUILD_DIR% mkdir %BUILD_DIR% + +REM 运行CMake配置 +pushd %BUILD_DIR% +echo Running CMake configuration... +cmake .. -G %CMAKE_GENERATOR% -DCMAKE_INSTALL_PREFIX=../%INSTALL_PREFIX% +if %ERRORLEVEL% neq 0 ( + echo CMake configuration failed! + popd + exit /b 1 +) + +REM 构建项目 +echo Building project... +cmake --build . --config Release +if %ERRORLEVEL% neq 0 ( + echo Build failed! + popd + exit /b 1 +) + +REM 安装项目 +echo Installing project... +cmake --build . --config Release --target install +if %ERRORLEVEL% neq 0 ( + echo Installation failed! + popd + exit /b 1 +) + +popd + +echo Build completed successfully! +echo Server executable: %INSTALL_PREFIX%\bin\rpc_server.exeecho Client executable: %INSTALL_PREFIX%\bin\rpc_client.exe +echo +echo To run the server: +cd %INSTALL_PREFIX%\bin +echo rpc_server.exe + +echo +echo Then in another terminal: echo rpc_client.exe \ No newline at end of file diff --git a/scalib/convert_encoding.py b/scalib/convert_encoding.py new file mode 100644 index 0000000..78e35a5 --- /dev/null +++ b/scalib/convert_encoding.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +转换项目中的所有文件编码为UTF-8无BOM格式(Linux兼容) +""" + +import os +import codecs + +def convert_file_to_utf8_no_bom(file_path): + """将单个文件转换为UTF-8无BOM格式""" + try: + # 尝试自动检测文件编码并读取内容 + with open(file_path, 'rb') as f: + content = f.read() + + # 尝试几种常见的编码格式 + encodings = ['utf-8', 'utf-8-sig', 'gbk', 'gb2312', 'latin-1'] + text = None + + for encoding in encodings: + try: + text = content.decode(encoding) + break + except UnicodeDecodeError: + continue + + if text is None: + # 如果无法解码,使用二进制模式复制 + print(f"警告: 无法解码文件 {file_path},使用二进制模式复制") + with open(file_path + '.tmp', 'wb') as f: + f.write(content) + os.replace(file_path + '.tmp', file_path) + return False + + # 以UTF-8无BOM格式写入文件 + with open(file_path + '.tmp', 'w', encoding='utf-8') as f: + f.write(text) + + # 替换原文件 + os.replace(file_path + '.tmp', file_path) + + print(f"已转换: {file_path}") + return True + + except Exception as e: + print(f"错误: 转换文件 {file_path} 失败 - {str(e)}") + return False + +def main(): + """主函数""" + # 设置项目根目录 + project_root = os.path.dirname(os.path.abspath(__file__)) + + # 定义需要转换的文件列表 + files_to_convert = [ + # 根目录下的文件 + '.gitignore', + 'CMakeLists.txt', + 'README.md', + 'build.sh', + 'build_windows.bat', + 'test_cmake_config.cmd', + 'test_compile.cmd', + + # include目录下的文件 + os.path.join('include', 'rpc_common.h'), + os.path.join('include', 'rpc_message.h'), + os.path.join('include', 'rpc_transport.h'), + + # src目录下的文件 + os.path.join('src', 'CMakeLists.txt'), + os.path.join('src', 'rpc_client.c'), + os.path.join('src', 'rpc_common.c'), + os.path.join('src', 'rpc_message.c'), + os.path.join('src', 'rpc_server.c'), + os.path.join('src', 'rpc_transport.c') + ] + + print(f"开始转换项目文件编码为UTF-8无BOM格式(Linux兼容)...") + print(f"项目根目录: {project_root}") + print("=" * 60) + + # 转换每个文件 + success_count = 0 + error_count = 0 + + for file_rel_path in files_to_convert: + file_abs_path = os.path.join(project_root, file_rel_path) + + if os.path.exists(file_abs_path): + if convert_file_to_utf8_no_bom(file_abs_path): + success_count += 1 + else: + error_count += 1 + else: + print(f"警告: 文件不存在 - {file_abs_path}") + error_count += 1 + + print("=" * 60) + print(f"转换完成!成功: {success_count}, 失败: {error_count}") + print("所有文件已转换为UTF-8无BOM格式,可以在Linux环境下正常使用。") + + # 让窗口保持打开状态 + input("按Enter键退出...") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scalib/include/rpc_message.h b/scalib/include/rpc_message.h index 089e7c7..a37abf3 100644 --- a/scalib/include/rpc_message.h +++ b/scalib/include/rpc_message.h @@ -1,59 +1,59 @@ -/* - * rpc_message.h - * 定义RPC消息的序列化和反序列化接口 - */ - -#ifndef RPC_MESSAGE_H -#define RPC_MESSAGE_H - -#include "rpc_common.h" -#include "rpc_transport.h" - -/* 消息类型枚举 */ -typedef enum { - RPC_MESSAGE_REQUEST, // 请求消息 - RPC_MESSAGE_RESPONSE // 响应消息 -} rpc_message_type_t; - -/* RPC消息头部 */ -typedef struct { - rpc_message_type_t type; // 消息类型 - uint32_t payload_size; // 负载大小 -} rpc_message_header_t; - -/* RPC消息结构 */ -typedef struct { - rpc_message_header_t header; // 消息头部 - union { - rpc_request_t request; // 请求消息 - rpc_response_t response; // 响应消息 - } payload; // 消息负载 -} rpc_message_t; - -/* 消息处理函数声明 */ - -// 序列化请求消息到缓冲区 -int rpc_serialize_request(const rpc_request_t* request, void* buffer, size_t buffer_size); - -// 反序列化缓冲区到请求消息 -int rpc_deserialize_request(const void* buffer, size_t buffer_size, rpc_request_t* request); - -// 序列化响应消息到缓冲区 -int rpc_serialize_response(const rpc_response_t* response, void* buffer, size_t buffer_size); - -// 反序列化缓冲区到响应消息 -int rpc_deserialize_response(const void* buffer, size_t buffer_size, rpc_response_t* response); - -// 发送请求消息 -int rpc_send_request(rpc_transport_t* transport, const rpc_request_t* request); - -// 接收请求消息 -int rpc_recv_request(rpc_transport_t* transport, rpc_request_t* request); - -// 发送响应消息 -int rpc_send_response(rpc_transport_t* transport, const rpc_response_t* response); - -// 接收响应消息 -int rpc_recv_response(rpc_transport_t* transport, rpc_response_t* response); - +/* + * rpc_message.h + * 定义RPC消息的序列化和反序列化接口 + */ + +#ifndef RPC_MESSAGE_H +#define RPC_MESSAGE_H + +#include "rpc_common.h" +#include "rpc_transport.h" + +/* 消息类型枚举 */ +typedef enum { + RPC_MESSAGE_REQUEST, // 请求消息 + RPC_MESSAGE_RESPONSE // 响应消息 +} rpc_message_type_t; + +/* RPC消息头部 */ +typedef struct { + rpc_message_type_t type; // 消息类型 + uint32_t payload_size; // 负载大小 +} rpc_message_header_t; + +/* RPC消息结构 */ +typedef struct { + rpc_message_header_t header; // 消息头部 + union { + rpc_request_t request; // 请求消息 + rpc_response_t response; // 响应消息 + } payload; // 消息负载 +} rpc_message_t; + +/* 消息处理函数声明 */ + +// 序列化请求消息到缓冲区 +int rpc_serialize_request(const rpc_request_t* request, void* buffer, size_t buffer_size); + +// 反序列化缓冲区到请求消息 +int rpc_deserialize_request(const void* buffer, size_t buffer_size, rpc_request_t* request); + +// 序列化响应消息到缓冲区 +int rpc_serialize_response(const rpc_response_t* response, void* buffer, size_t buffer_size); + +// 反序列化缓冲区到响应消息 +int rpc_deserialize_response(const void* buffer, size_t buffer_size, rpc_response_t* response); + +// 发送请求消息 +int rpc_send_request(rpc_transport_t* transport, const rpc_request_t* request); + +// 接收请求消息 +int rpc_recv_request(rpc_transport_t* transport, rpc_request_t* request); + +// 发送响应消息 +int rpc_send_response(rpc_transport_t* transport, const rpc_response_t* response); + +// 接收响应消息 +int rpc_recv_response(rpc_transport_t* transport, rpc_response_t* response); + #endif /* RPC_MESSAGE_H */ \ No newline at end of file diff --git a/scalib/include/rpc_transport.h b/scalib/include/rpc_transport.h index fdeaa68..2cb603a 100644 --- a/scalib/include/rpc_transport.h +++ b/scalib/include/rpc_transport.h @@ -1,77 +1,77 @@ -/* - * rpc_transport.h - * 定义RPC传输层的接口,负责处理网络通信 - */ - -#ifndef RPC_TRANSPORT_H -#define RPC_TRANSPORT_H - -#include "rpc_common.h" - -/* 根据不同平台包含不同的头文件 */ -#ifdef _WIN32 - #include - #include - #pragma comment(lib, "ws2_32.lib") - - /* Windows平台的类型定义 */ - typedef SOCKET socket_t; - #define INVALID_SOCKET_VALUE INVALID_SOCKET - #define CLOSE_SOCKET(s) closesocket(s) - - /* Windows平台初始化和清理函数 */ - int rpc_winsock_init(); - void rpc_winsock_cleanup(); -#else - /* Linux/Unix平台的头文件 */ - #include - #include - #include - #include - - /* Linux/Unix平台的类型定义 */ - typedef int socket_t; - #define INVALID_SOCKET_VALUE (-1) - #define CLOSE_SOCKET(s) close(s) - - /* Linux/Unix平台不需要特殊的初始化和清理 */ - #define rpc_winsock_init() 0 - #define rpc_winsock_cleanup() -#endif - -/* 传输上下文 */ -typedef struct { - socket_t socket_fd; // 套接字文件描述符 - struct sockaddr_in address; // 地址信息 -} rpc_transport_t; - -/* 服务器上下文 */ -typedef struct { - socket_t server_fd; // 服务器套接字文件描述符 - struct sockaddr_in address; // 服务器地址信息 -} rpc_server_t; - -/* 传输层函数声明 */ - -// 初始化服务器 -int rpc_server_init(rpc_server_t* server, const char* host, uint16_t port, int backlog); - -// 服务器等待连接 -int rpc_server_accept(rpc_server_t* server, rpc_transport_t* transport); - -// 关闭服务器 -void rpc_server_close(rpc_server_t* server); - -// 初始化客户端传输 -int rpc_client_init(rpc_transport_t* transport, const char* server_host, uint16_t server_port); - -// 发送数据 -int rpc_transport_send(rpc_transport_t* transport, const void* data, size_t data_size); - -// 接收数据 -int rpc_transport_recv(rpc_transport_t* transport, void* buffer, size_t buffer_size); - -// 关闭传输连接 -void rpc_transport_close(rpc_transport_t* transport); - +/* + * rpc_transport.h + * 定义RPC传输层的接口,负责处理网络通信 + */ + +#ifndef RPC_TRANSPORT_H +#define RPC_TRANSPORT_H + +#include "rpc_common.h" + +/* 根据不同平台包含不同的头文件 */ +#ifdef _WIN32 + #include + #include + #pragma comment(lib, "ws2_32.lib") + + /* Windows平台的类型定义 */ + typedef SOCKET socket_t; + #define INVALID_SOCKET_VALUE INVALID_SOCKET + #define CLOSE_SOCKET(s) closesocket(s) + + /* Windows平台初始化和清理函数 */ + int rpc_winsock_init(); + void rpc_winsock_cleanup(); +#else + /* Linux/Unix平台的头文件 */ + #include + #include + #include + #include + + /* Linux/Unix平台的类型定义 */ + typedef int socket_t; + #define INVALID_SOCKET_VALUE (-1) + #define CLOSE_SOCKET(s) close(s) + + /* Linux/Unix平台不需要特殊的初始化和清理 */ + #define rpc_winsock_init() 0 + #define rpc_winsock_cleanup() +#endif + +/* 传输上下文 */ +typedef struct { + socket_t socket_fd; // 套接字文件描述符 + struct sockaddr_in address; // 地址信息 +} rpc_transport_t; + +/* 服务器上下文 */ +typedef struct { + socket_t server_fd; // 服务器套接字文件描述符 + struct sockaddr_in address; // 服务器地址信息 +} rpc_server_t; + +/* 传输层函数声明 */ + +// 初始化服务器 +int rpc_server_init(rpc_server_t* server, const char* host, uint16_t port, int backlog); + +// 服务器等待连接 +int rpc_server_accept(rpc_server_t* server, rpc_transport_t* transport); + +// 关闭服务器 +void rpc_server_close(rpc_server_t* server); + +// 初始化客户端传输 +int rpc_client_init(rpc_transport_t* transport, const char* server_host, uint16_t server_port); + +// 发送数据 +int rpc_transport_send(rpc_transport_t* transport, const void* data, size_t data_size); + +// 接收数据 +int rpc_transport_recv(rpc_transport_t* transport, void* buffer, size_t buffer_size); + +// 关闭传输连接 +void rpc_transport_close(rpc_transport_t* transport); + #endif /* RPC_TRANSPORT_H */ \ No newline at end of file diff --git a/scalib/src/CMakeLists.txt b/scalib/src/CMakeLists.txt index 16b9120..e29a52d 100644 --- a/scalib/src/CMakeLists.txt +++ b/scalib/src/CMakeLists.txt @@ -1,55 +1,55 @@ -# 输出目录设置由顶层CMakeLists.txt控制 -# 以下设置已被禁用,使用顶层设置 -# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -# set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - -# RPC共享库 -add_library(rpc_common STATIC - rpc_common.c - rpc_message.c - rpc_transport.c -) - -# RPC服务器 -add_executable(rpc_server - rpc_server.c -) - -# 根据不同平台链接不同的库 -if(WIN32) - target_link_libraries(rpc_server - rpc_common - ws2_32 # Windows套接字库 - ) -else() - target_link_libraries(rpc_server - rpc_common - pthread - ) -endif() - -# RPC客户端 -add_executable(rpc_client - rpc_client.c -) - -# 根据不同平台链接不同的库 -if(WIN32) - target_link_libraries(rpc_client - rpc_common - ws2_32 # Windows套接字库 - ) -else() - target_link_libraries(rpc_client - rpc_common - pthread - ) -endif() - -# 安装目标 -install(TARGETS rpc_common rpc_server rpc_client - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib +# 输出目录设置由顶层CMakeLists.txt控制 +# 以下设置已被禁用,使用顶层设置 +# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +# set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +# RPC共享库 +add_library(rpc_common STATIC + rpc_common.c + rpc_message.c + rpc_transport.c +) + +# RPC服务器 +add_executable(rpc_server + rpc_server.c +) + +# 根据不同平台链接不同的库 +if(WIN32) + target_link_libraries(rpc_server + rpc_common + ws2_32 # Windows套接字库 + ) +else() + target_link_libraries(rpc_server + rpc_common + pthread + ) +endif() + +# RPC客户端 +add_executable(rpc_client + rpc_client.c +) + +# 根据不同平台链接不同的库 +if(WIN32) + target_link_libraries(rpc_client + rpc_common + ws2_32 # Windows套接字库 + ) +else() + target_link_libraries(rpc_client + rpc_common + pthread + ) +endif() + +# 安装目标 +install(TARGETS rpc_common rpc_server rpc_client + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib ) \ No newline at end of file diff --git a/scalib/src/rpc_common.c b/scalib/src/rpc_common.c index 15f220f..1475eeb 100644 --- a/scalib/src/rpc_common.c +++ b/scalib/src/rpc_common.c @@ -1,97 +1,97 @@ -/* - * 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: - 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"; - } +/* + * 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: + 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"; + } } \ No newline at end of file diff --git a/scalib/src/rpc_message.c b/scalib/src/rpc_message.c index c20f188..95eb04a 100644 --- a/scalib/src/rpc_message.c +++ b/scalib/src/rpc_message.c @@ -1,191 +1,191 @@ -/* - * 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; +/* + * 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; } \ No newline at end of file diff --git a/scalib/src/rpc_server.c b/scalib/src/rpc_server.c index 1704ca8..c0b5874 100644 --- a/scalib/src/rpc_server.c +++ b/scalib/src/rpc_server.c @@ -1,296 +1,296 @@ -/* - * rpc_server.c - * RPC服务器实现,处理客户端连接和执行远程函数调用 - */ - -#include "rpc_common.h" -#include "rpc_transport.h" -#include "rpc_message.h" - -#ifdef _WIN32 -#include -#else -#include -#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; +/* + * rpc_server.c + * RPC服务器实现,处理客户端连接和执行远程函数调用 + */ + +#include "rpc_common.h" +#include "rpc_transport.h" +#include "rpc_message.h" + +#ifdef _WIN32 +#include +#else +#include +#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; } \ No newline at end of file diff --git a/scalib/src/rpc_transport.c b/scalib/src/rpc_transport.c index 14c1450..ab4d015 100644 --- a/scalib/src/rpc_transport.c +++ b/scalib/src/rpc_transport.c @@ -1,259 +1,259 @@ -/* - * 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(); -} - -/* - * 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) { - if (!server || !host) { - return RPC_INVALID_ARGS; - } - - // 创建套接字 - server->server_fd = socket(AF_INET, SOCK_STREAM, 0); - if (server->server_fd == INVALID_SOCKET_VALUE) { - PRINT_ERROR("socket creation failed"); - 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; - } - - // 设置服务器地址结构 - memset(&server->address, 0, sizeof(server->address)); - server->address.sin_family = AF_INET; - server->address.sin_addr.s_addr = inet_addr(host); - server->address.sin_port = htons(port); - - // 绑定地址到套接字 - if (bind(server->server_fd, (struct sockaddr*)&server->address, sizeof(server->address)) != 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; - } - - // 连接到服务器 - if (connect(transport->socket_fd, (struct sockaddr*)&transport->address, sizeof(transport->address)) != 0) { - 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; +/* + * 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(); +} + +/* + * 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) { + if (!server || !host) { + return RPC_INVALID_ARGS; + } + + // 创建套接字 + server->server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server->server_fd == INVALID_SOCKET_VALUE) { + PRINT_ERROR("socket creation failed"); + 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; + } + + // 设置服务器地址结构 + memset(&server->address, 0, sizeof(server->address)); + server->address.sin_family = AF_INET; + server->address.sin_addr.s_addr = inet_addr(host); + server->address.sin_port = htons(port); + + // 绑定地址到套接字 + if (bind(server->server_fd, (struct sockaddr*)&server->address, sizeof(server->address)) != 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; + } + + // 连接到服务器 + if (connect(transport->socket_fd, (struct sockaddr*)&transport->address, sizeof(transport->address)) != 0) { + 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; } \ No newline at end of file diff --git a/scalib/test_compile.cmd b/scalib/test_compile.cmd index cd03d22..cd2c239 100644 --- a/scalib/test_compile.cmd +++ b/scalib/test_compile.cmd @@ -1,33 +1,33 @@ -@echo off -REM 简单的测试编译脚本 - -REM 设置Visual Studio环境 -REM 尝试检测Visual Studio安装路径 -set VS170COMNTOOLS= -for /f "delims=" %%i in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v "17.0" 2^>nul') do ( - for /f "tokens=2*" %%j in ("%%i") do set "VS170COMNTOOLS=%%kCommon7\Tools\" -) - -REM 如果找不到Visual Studio 2022,尝试其他版本 -if not exist "%VS170COMNTOOLS%vsdevcmd.bat" ( - echo 无法找到Visual Studio 2022环境 - pause - exit /b 1 -) - -REM 设置环境变量 -call "%VS170COMNTOOLS%vsdevcmd.bat" -arch=x64 - -REM 设置编译选项 -set INCLUDE_DIR=include -set SRC_DIR=src - -REM 编译服务器 -cl.exe /I%INCLUDE_DIR% %SRC_DIR%\rpc_server.c %SRC_DIR%\rpc_common.c %SRC_DIR%\rpc_transport.c %SRC_DIR%\rpc_message.c /link ws2_32.lib /out:rpc_server_test.exe - -REM 检查编译结果 -if %ERRORLEVEL% EQU 0 ( - echo 编译成功!可执行文件: rpc_server_test.exe -) else ( - echo 编译失败! +@echo off +REM 简单的测试编译脚本 + +REM 设置Visual Studio环境 +REM 尝试检测Visual Studio安装路径 +set VS170COMNTOOLS= +for /f "delims=" %%i in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v "17.0" 2^>nul') do ( + for /f "tokens=2*" %%j in ("%%i") do set "VS170COMNTOOLS=%%kCommon7\Tools\" +) + +REM 如果找不到Visual Studio 2022,尝试其他版本 +if not exist "%VS170COMNTOOLS%vsdevcmd.bat" ( + echo 无法找到Visual Studio 2022环境 + pause + exit /b 1 +) + +REM 设置环境变量 +call "%VS170COMNTOOLS%vsdevcmd.bat" -arch=x64 + +REM 设置编译选项 +set INCLUDE_DIR=include +set SRC_DIR=src + +REM 编译服务器 +cl.exe /I%INCLUDE_DIR% %SRC_DIR%\rpc_server.c %SRC_DIR%\rpc_common.c %SRC_DIR%\rpc_transport.c %SRC_DIR%\rpc_message.c /link ws2_32.lib /out:rpc_server_test.exe + +REM 检查编译结果 +if %ERRORLEVEL% EQU 0 ( + echo 编译成功!可执行文件: rpc_server_test.exe +) else ( + echo 编译失败! ) \ No newline at end of file