赣州省住房和城乡建设厅网站企业软文营销发布平台
2026/4/17 16:16:12 网站建设 项目流程
赣州省住房和城乡建设厅网站,企业软文营销发布平台,软件著作权含金量,信誉好的做网站socket.c/*** file unix_socket_client.c* brief UNIX域套接字客户端实现* details 该文件实现了一个UNIX域流式套接字客户端#xff0c;用于本地进程间通信*/ ​ #include stdio.h /** 标准输入输出头文件#xff0c;提供printf等函数 */ #include str…socket.c/** * file unix_socket_client.c * brief UNIX域套接字客户端实现 * details 该文件实现了一个UNIX域流式套接字客户端用于本地进程间通信 */ ​ #include stdio.h /** 标准输入输出头文件提供printf等函数 */ #include string.h /** 字符串处理头文件提供strncpy等函数 */ #include stdlib.h /** 标准库头文件提供exit等函数 */ #include unistd.h /** UNIX标准函数头文件提供close、read、write等系统调用 */ #include sys/types.h /** 系统数据类型定义头文件提供pid_t、size_t等类型 */ #include sys/socket.h /** 套接字编程头文件提供socket、connect等函数 */ #include sys/un.h /** UNIX域套接字专用头文件定义sockaddr_un结构 */ #include sys/epoll.h /** epoll I/O多路复用头文件本程序未使用可移除 */ ​ #define SOCKET_PROTOCOL 0 /** 套接字协议0表示使用默认协议对于SOCK_STREAM通常是TCP或UNIX域流协议 */ #define SOCKET_KEY /mnt/user_data/UNIX.domain /** UNIX域套接字绑定的文件路径最大长度为sizeof(sun_path)-1通常107字节 */ ​ static int sock_fd -1; /** 全局套接字文件描述符-1表示未连接使用静态存储减少全局符号 */ ​ /** * brief 连接到服务器 * details 创建UNIX域流式套接字并连接到指定路径的服务器 * 设计模式封装模式隐藏套接字创建和连接细节 * 性能分析本地IPC延迟通常1ms使用内核缓冲区 * return 成功返回套接字描述符(0)失败返回-1 * retval 0 连接成功的套接字描述符 * retval -1 连接失败 */ int connect_sever(void) { struct sockaddr_un srv_addr; /** UNIX域套接字地址结构大小由宏SUN_LEN确定 */ ​ /** * 创建UNIX域流式套接字 * AF_UNIX: 本地通信协议族 * SOCK_STREAM: 面向连接的字节流套接字 * 0: 使用默认协议 * 性能内核中创建socket结构体分配inode和文件描述符 */ sock_fd socket(AF_UNIX, SOCK_STREAM, SOCKET_PROTOCOL); if (sock_fd 0) { return -1; /** 套接字创建失败通常因资源耗尽或权限不足 */ } ​ srv_addr.sun_family AF_UNIX; /** 协议族必须为AF_UNIX */ /** * 复制套接字路径到地址结构 * sizeof(srv_addr.sun_path)-1: 保留一个字节给空终止符 * SUN_PATH长度通常为108字节包括空字符 */ strncpy(srv_addr.sun_path, SOCKET_KEY, sizeof(srv_addr.sun_path) - 1); /** * 连接到服务器 * sock_fd: 客户端套接字描述符 * (struct sockaddr*)srv_addr: 服务器地址结构指针 * sizeof(srv_addr): 地址结构实际大小非固定取决于路径长度 * 性能内核验证路径是否存在可连接的套接字建立连接控制块 */ if (connect(sock_fd, (struct sockaddr*)srv_addr, sizeof(srv_addr))) { goto err; /** 连接失败跳转到错误处理 */ } ​ return sock_fd; /** 连接成功返回套接字描述符 */ ​ err: close(sock_fd); /** 关闭已创建的套接字描述符 */ return -1; /** 返回错误标志 */ } ​ /** * brief 断开服务器连接 * details 关闭套接字并重置描述符 * 设计模式资源管理包装器 * 性能分析立即释放内核资源但需注意多次关闭安全问题 * return void */ void disconnect_sever(void) { if (sock_fd 0) /** 检查套接字是否已连接 */ return; ​ close(sock_fd); /** 系统调用释放套接字相关资源 */ sock_fd -1; /** 重置为无效状态防止重复关闭 */ } ​ /** * brief 向服务器发送数据 * details 通过已连接的套接字发送指定长度的数据 * 设计模式适配器模式将write系统调用包装为应用接口 * 性能分析使用内核缓冲区可能因缓冲区满而阻塞 * param[in] buf 待发送数据的缓冲区指针 * param[in] cont 要发送的字节数≤缓冲区实际大小 * return 成功返回发送的字节数失败返回-1 * retval 0 实际发送的字节数 * retval -1 发送失败 */ int send_severce_date(unsigned char *buf, int cont) { int ret; ​ if (sock_fd 0) { /** 验证套接字连接状态 */ return -1; } ​ /** * 写入数据到套接字 * sock_fd: 已连接的套接字描述符 * buf: 用户空间数据缓冲区 * cont: 请求写入的字节数 * 注意可能部分写入但本实现要求完全写入 */ ret write(sock_fd, buf, cont); if (ret ! cont) { /** 实际写入字节不等于请求字节 */ return -1; /** 可能原因连接中断、资源不足、信号中断 */ } ​ return ret; /** 返回成功发送的字节数 */ } ​ /** * brief 从服务器接收数据 * details 从套接字读取指定长度的数据到缓冲区 * 设计模式适配器模式包装read系统调用 * 性能分析可能阻塞等待数据到达使用内核缓冲区 * param[out] buf 接收数据的缓冲区指针 * param[in] cont 期望接收的最大字节数≤缓冲区大小 * return 成功返回接收的字节数失败返回-1 * retval 0 实际接收的字节数可能小于cont * retval 0 对端关闭连接 * retval -1 读取失败 */ int revc_severce_data(unsigned char *buf, int cont) { int ret; ​ if (sock_fd 0) { /** 验证套接字连接状态 */ return -1; } ​ /** * 从套接字读取数据 * sock_fd: 已连接的套接字描述符 * buf: 用户空间接收缓冲区 * cont: 缓冲区最大容量 * 注意可能返回少于请求的字节数 */ ret read(sock_fd, buf, cont); if (ret 0) { /** 读取错误连接问题、信号中断等 */ return -1; } ​ return ret; /** 返回实际读取字节数0表示EOF */ } ​main.c/** * file unix_socket_client_app.c * brief UNIX域套接字客户端应用程序 * details 实现客户端主程序包含信号处理、命令解析和事件驱动通信 */ ​ #include stdio.h /** 标准输入输出头文件提供printf、sprintf等函数 */ #include string.h /** 字符串处理头文件提供memset、memmove、strncmp等函数 */ #include stdlib.h /** 标准库头文件提供calloc、free等内存管理函数 */ #include unistd.h /** UNIX标准函数头文件提供readlink、usleep、_exit等系统调用 */ #include errno.h /** 错误号头文件提供errno全局变量本程序未使用 */ #include signal.h /** 信号处理头文件提供sigaction、sigemptyset等函数 */ #include sys/types.h /** 系统数据类型定义头文件提供size_t等类型 */ #include sys/epoll.h /** epoll I/O多路复用头文件提供epoll_create、epoll_wait等函数 */ ​ #define GET_EXELINK /proc/self/exe /** 获取当前可执行文件符号链接的路径Linux特有proc文件系统接口 */ ​ /* 前置声明假设在另一个文件中定义 */ int revc_severce_data(unsigned char *buf, int cont); /** 从服务器接收数据函数声明 */ int send_severce_date(unsigned char *buf, int cont); /** 向服务器发送数据函数声明 */ int connect_sever(void); /** 连接服务器函数声明 */ void disconnect_sever(void); /** 断开连接函数声明 */ ​ /** * brief 从服务器接收并显示数据 * details 接收服务器发送的数据并在标准输出显示 * 设计模式观察者模式响应服务器数据到达事件 * 性能分析使用4KB缓冲区适合小消息传输 * return 成功返回0失败返回-1 * retval 0 接收并显示成功 * retval -1 接收失败或连接断开 */ int recv_from_sever_data(void) { int ret 0; unsigned char buf[4096]; /** 接收缓冲区4KB大小适合大多数IPC消息 */ ​ memset(buf, 0x0, sizeof(buf)); /** 清空缓冲区防止残留数据干扰 */ ret revc_severce_data(buf, sizeof(buf)); /** 调用底层接收函数 */ if (ret 0) { /** 返回值0表示错误或连接关闭 */ return -1; } ​ printf(%s, buf); /** 输出接收到的数据到标准输出假设为文本格式 */ return 0; } ​ /** * brief 处理执行命令行参数 * details 解析命令行参数构建发送给服务器的命令字符串 * 设计模式构建器模式逐步构建命令字符串 * 性能分析O(n)复杂度n为参数个数 * param[in] count 命令行参数个数argc * param[in] chr 命令行参数数组argv * return 成功返回0失败返回-1 * retval 0 命令处理并发送成功 * retval -1 读取符号链接失败或发送失败 */ int dispose_exec_cmdline(int count, char *chr[]) { int i, ret, len, fd; /** fd未使用可移除 */ char *ofs NULL; /** 指向可执行文件名在路径中的位置 */ char soft_name[256]; /** 存储可执行文件路径最大255字符空终止符 */ char cmdline[1024]; /** 命令缓冲区1KB容量足够存储典型命令行 */ ​ /** * 读取/proc/self/exe符号链接获取可执行文件真实路径 * 性能文件系统操作通常1ms结果被内核缓存 * 注意在chroot环境或特殊权限下可能失败 */ ret readlink(GET_EXELINK, soft_name, sizeof(soft_name)); if (ret 0) { /** 读取失败或路径为空 */ return -1; } ofs strrchr(soft_name, /) 1; /** 查找最后一个/定位文件名开始位置 */ len ret - (ofs - soft_name); /** 计算文件名长度不包括路径分隔符 */ memmove(soft_name, ofs, len); /** 将文件名移动到缓冲区开头原地移动 */ memset(soft_name len, 0x0, sizeof(soft_name)); /** 清空剩余部分 */ ​ memset(cmdline, 0x0, sizeof(cmdline)); /** 清空命令缓冲区 */ for (i 0; i count; i) { /** * 拼接所有命令行参数用空格分隔 * 注意sprintf可能造成缓冲区溢出但1024缓冲区通常足够 * 性能O(n)字符串拼接每次计算strlen效率较低 */ sprintf(cmdline strlen(cmdline), %s , chr[i]); } sprintf(cmdline strlen(cmdline), \n); /** 添加换行符作为命令结束标志 */ ​ len strlen(cmdline); /** 获取当前命令总长度 */ /** 移除开头的./前缀如果存在 */ if (strncmp(cmdline, ./, 2) 0) { memmove(cmdline, cmdline 2, len - 2); /** 向前移动字符串移除./ */ len - 2; /** 更新长度 */ memset(cmdline len, 0x0, len); /** 清空移动后空出的部分 */ } ​ /** 移除可执行文件名如果命令以程序名开头 */ if (strncmp(cmdline, soft_name, strlen(soft_name)) 0) { /** * 移除程序名和后面的空格 * 1用于跳过程序名后的空格 */ memmove(cmdline, cmdline strlen(soft_name) 1, len - strlen(soft_name)); len - strlen(soft_name); /** 更新长度 */ memset(cmdline len, 0x0, len); /** 清空末尾 */ } ​ /** 发送处理后的命令到服务器 */ if (send_severce_date(cmdline, len) 0) /** 发送失败 */ return -1; ​ return 0; } ​ /** * brief 信号处理函数 * details 处理SIGINT等信号执行清理操作后退出 * 设计模式回调模式注册到信号系统 * 性能分析信号处理应尽量快速避免复杂操作 * param[in] signal_id 信号编号如SIGINT2 * param[in] sig_info 信号详细信息结构体siginfo_t * param[in] context 信号上下文ucontext_t * return void */ void signal_handle(int signal_id, siginfo_t *sig_info, void *context) { static int debug 0; /** 调试标志未使用 */ ​ //printf(Recv %d signal, exit this !\n, signal_id); disconnect_sever(); /** 断开服务器连接 */ usleep(1000 * 500); /** 休眠500ms确保清理完成可能不必要 */ _exit(1); /** 立即退出进程不执行atexit注册的函数 */ } ​ /** * brief 信号管理设置 * details 配置信号处理函数捕获SIGINTCtrlC信号 * 设计模式初始化模式 * 性能分析一次性设置无运行时开销 * return void */ void signal_manage(void) { struct sigaction sig; /** 信号动作结构体 */ ​ sig.sa_sigaction (void *)signal_handle; /** 设置信号处理函数指针 */ sigemptyset(sig.sa_mask); /** 清空信号掩码处理时不阻塞其他信号 */ sig.sa_flags SA_RESTART | SA_SIGINFO; /** 标志系统调用自动重启使用sa_sigaction */ sigaction(SIGINT, sig, NULL); /** 注册SIGINT信号处理 */ } ​ /** * brief 主函数 * details 程序入口点初始化epoll连接服务器发送命令并等待响应 * 设计模式反应堆模式Reactor事件驱动架构 * 性能分析epoll实现O(1)事件检测适合高并发但本程序只监控单个fd * param[in] argc 命令行参数个数 * param[in] argv 命令行参数数组 * return 成功返回0失败返回-1 */ int main(int argc, char *argv[]) { int num, ret; /** 临时变量epoll事件数和函数返回值 */ int sfd -1; /** 套接字文件描述符初始为无效 */ int efd -1; /** epoll文件描述符初始为无效 */ ​ struct epoll_event event[1]; /** epoll事件数组用于添加fd到epoll */ struct epoll_event *pevent NULL; /** epoll事件指针用于接收就绪事件 */ ​ signal_manage(); /** 设置信号处理确保程序可被CtrlC优雅终止 */ ​ // 创建Epoll文件I/O多路复用实例 /** * 创建epoll实例参数已被忽略但必须0返回epoll文件描述符 * 性能内核分配epoll结构初始开销小 * 注意现代Linux忽略size参数但保持向后兼容 */ efd epoll_create(1); if (efd 0) { /** 创建失败通常因资源耗尽或权限问题 */ printf(E501: internal error!); return -1; } ​ // 连接到远程服务器的socket sfd connect_sever(); /** 连接服务器获取套接字描述符 */ if (sfd 0) { /** 连接失败 */ goto exit0; /** 跳转到错误处理 */ } /** 配置epoll事件 */ event[0].data.fd sfd; /** 关联套接字描述符 */ event[0].events EPOLLIN; /** 监控可读事件数据到达 */ ​ /** 将套接字添加到epoll监控集合 */ ret epoll_ctl(efd, EPOLL_CTL_ADD, sfd, event[0]); if (ret 0) { /** 添加失败通常因efd无效或权限问题 */ goto exit1; } ​ /** 分配epoll事件接收缓冲区 */ pevent calloc(1, sizeof(event)); /** 分配并清零内存防止未初始化数据 */ if (pevent NULL) { /** 内存分配失败 */ goto exit1; } ​ /** 处理并发送命令行参数到服务器 */ if (dispose_exec_cmdline(argc, argv) 0) goto exit2; ​ /** 主事件循环 */ while (1) { /** * 等待epoll事件超时时间2秒1000*2毫秒 * 参数 * efd: epoll实例描述符 * pevent: 事件接收数组 * 1: 最大返回事件数只需监控一个fd * (1000*2): 超时时间2000ms * 性能系统调用无事件时休眠减少CPU占用 */ num epoll_wait(efd, pevent, 1, (1000 * 2)); if (num 0) { /** 有事件发生 */ /** 检查是否为套接字可读事件 */ if ((sfd pevent[0].data.fd) (pevent[0].events EPOLLIN)) { if (recv_from_sever_data() 0) /** 接收并处理数据 */ break; /** 接收失败退出循环 */ ​ } else { /** 未知事件或错误事件 */ goto exit2; } } /** 超时num0时继续循环实现轮询机制 */ } ​ /** 正常退出路径释放资源 */ free(pevent); /** 释放动态分配的内存 */ close(efd); /** 关闭epoll文件描述符 */ disconnect_sever(); /** 断开服务器连接 */ return 0; ​ /** 错误处理路径标签式资源清理 */ exit2: free(pevent); /** 释放已分配的事件内存 */ exit1: disconnect_sever(); /** 断开连接如果已连接 */ exit0: close(efd); /** 关闭epoll描述符如果已创建 */ printf(E501: internal error!); /** 输出错误信息到标准错误更合适 */ return -1; } ​远程控制客户端 Makefile# # 远程控制客户端 Makefile # ​ # ---------------------------------------------------------------------------- # 1. 路径配置部分 # ---------------------------------------------------------------------------- ​ # ROOTFS_PATH: 根文件系统路径指向项目根目录的上两级目录 # 用途构建嵌入式系统的根文件系统结构 # 默认值../../ ROOTFS_PATH ../../ ​ # INC_PATH: 头文件搜索路径可被外部环境变量覆盖 # ? 条件赋值仅当变量未定义时赋值 # 用途包含共享的头文件如自定义库或内核头文件 # 默认值$(ROOTFS_PATH)include/ INC_PATH ? $(ROOTFS_PATH)include/ ​ # BIN_PATH: 可执行文件安装路径 # 用途存放编译后的可执行程序 # 默认值$(ROOTFS_PATH)image/user_rootfs/bin BIN_PATH ? $(ROOTFS_PATH)image/user_rootfs/bin ​ # LIBS_PATH: 库文件安装路径本Makefile中未使用 # 用途存放动态链接库或静态库 # 默认值$(ROOTFS_PATH)image/user_rootfs/lib LIBS_PATH ? $(ROOTFS_PATH)image/user_rootfs/lib ​ # ---------------------------------------------------------------------------- # 2. 工具链配置部分 # ---------------------------------------------------------------------------- ​ # COMPILE: 交叉编译工具链 # arm-linux-gcc: 针对ARM架构的Linux交叉编译器 # 说明用于嵌入式ARM平台开发生成ARM架构的可执行文件 COMPILE arm-linux-gcc ​ # ---------------------------------------------------------------------------- # 3. 目标文件配置部分 # ---------------------------------------------------------------------------- ​ # FINAL_TARGET: 最终生成的可执行文件名 # remote_box: 远程控制客户端程序名称 FINAL_TARGET remote_box ​ # INSTALL_TARGET: 安装目标路径 # 复用BIN_PATH变量确保安装到正确位置 INSTALL_TARGET $(BIN_PATH) ​ # OBJS: 目标文件列表 # main.o: 主程序文件编译后的目标文件 # socket.o: 套接字通信模块的目标文件 # 扩展可通过模式匹配自动生成如 OBJS $(patsubst %.c,%.o,$(wildcard *.c)) OBJS main.o socket.o ​ # ---------------------------------------------------------------------------- # 4. 伪目标声明部分 # ---------------------------------------------------------------------------- ​ # .PHONY: 声明伪目标避免与同名文件冲突 # all: 默认构建目标 # install: 安装目标 # clean: 清理目标 .PHONY : all all : $(FINAL_TARGET) ​ # ---------------------------------------------------------------------------- # 5. 构建规则部分 # ---------------------------------------------------------------------------- ​ # 最终目标链接规则 # 依赖$(OBJS)main.o和socket.o # 命令使用交叉编译器将目标文件链接为可执行文件 # -o: 指定输出文件名 $(FINAL_TARGET) : $(OBJS) $(COMPILE) -o $(FINAL_TARGET) $(OBJS) ​ # 模式规则C源文件编译规则 # %.o : %.c: 任意.o文件依赖于同名的.c文件 # $: 第一个依赖文件.c文件 # $: 目标文件.o文件 # CFLAGS: 编译选项变量可在外部定义本Makefile中未设置默认值 %.o : %.c $(COMPILE) -c $(CFLAGS) $ -o $ ​ # ---------------------------------------------------------------------------- # 6. 安装规则部分 # ---------------------------------------------------------------------------- ​ # install: 安装可执行文件到目标路径 # cp -f: 强制复制覆盖已存在的文件 # echo: 静默模式输出信息前缀抑制命令回显 .PHONY : install install : cp -f $(FINAL_TARGET) $(INSTALL_TARGET) echo install remote_client finish!!! ​ # ---------------------------------------------------------------------------- # 7. 清理规则部分 # ---------------------------------------------------------------------------- ​ # clean: 清理生成的文件 # rm -rf: 递归强制删除 # 清理对象所有目标文件($(OBJS))和最终可执行文件($(FINAL_TARGET)) .PHONY : clean clean : rm -rf $(OBJS) $(FINAL_TARGET)程序/模块架构分析一、树形架构结构remote_box (ARM可执行文件) ├── main.o (主程序模块) │ ├── 事件循环管理 │ ├── epoll监控 │ ├── 命令行解析 │ └── 信号处理 └── socket.o (网络通信模块) ├── UNIX域套接字连接 ├── 数据发送(send_severce_date) ├── 数据接收(revc_severce_data) └── 连接管理(connect_sever/disconnect_sever)二、软件设计架构思想1.分层架构应用层 (main.c) ├── 用户交互层 (信号处理、控制循环) └── 业务逻辑层 (命令解析、事件分发) 服务层 (socket.c) ├── 传输层 (数据收发) └── 连接层 (连接管理)2.模块化设计通信模块独立: socket.c封装所有网络操作提供清晰API主控模块专注业务: main.c处理程序流程和用户交互松耦合接口: 通过函数声明连接便于单元测试3.嵌入式系统设计模式交叉编译兼容: 明确指定ARM工具链根文件系统集成: 路径配置支持嵌入式部署最小化依赖: 只依赖标准C库和系统调用三、系统源码树形结构项目根目录/ ├── ../../ (ROOTFS_PATH) │ ├── include/ # 共享头文件 │ └── image/ │ └── user_rootfs/ # 目标根文件系统 │ ├── bin/ # 安装目标路径 │ └── lib/ # 库文件路径 ├── src/ # 源代码目录 │ ├── Makefile # 本构建文件 │ ├── main.c # 主程序 │ └── socket.c # 套接字模块 ├── build/ # 编译输出目录(隐含) │ ├── main.o │ ├── socket.o │ └── remote_box └── docs/ # 文档目录(建议)四、Makefile设计模式分析1.模板方法模式定义通用规则:%.o : %.c模式规则具体实现延迟: 具体编译选项通过CFLAGS外部注入2.工厂方法模式目标工厂: 根据依赖自动选择构建路径产品族: 生成.o中间文件和最终可执行文件3.策略模式工具链策略:COMPILE变量定义编译器安装策略:install目标提供部署策略五、构建系统特性1.增量编译文件级依赖检测仅重新编译修改的文件通过.o目标文件实现中间缓存2.交叉编译支持明确指定ARM架构目标路径配置适应嵌入式部署3.灵活配置路径变量使用条件赋值(?)支持外部覆盖CFLAGS变量为空但可扩展六、改进建议1.安全性增强# 添加编译警告和安全标志 CFLAGS ? -Wall -Wextra -Werror -O2 -fstack-protector2.依赖管理# 自动生成头文件依赖 DEPFLAGS -MMD -MP DEPS $(OBJS:.o.d) -include $(DEPS)3.目录结构优化# 分离源码和构建目录 BUILD_DIR build OBJS $(addprefix $(BUILD_DIR)/, $(notdir $(SRCS:.c.o)))4.安装优化# 添加安装权限设置 install : install -m 755 $(FINAL_TARGET) $(INSTALL_TARGET) echo Installation complete七、典型使用流程# 1. 清理构建环境 make clean ​ # 2. 编译程序 make all ​ # 3. 安装到根文件系统 make install ​ # 4. 交叉编译示例外部设置 export CFLAGS-O2 -Wall make

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询