Windows平台C语言Socket服务端集成Salt通道后仅响应最后连接客户端问题
问题根因
- 仅使用单个全局
CLIENT*指针存储客户端信息,每次新客户端接入都会覆盖该指针值,后续处理非监听套接字的消息时,永远只会操作最后一个接入的客户端的salt_channel_t上下文,旧客户端的上下文完全丢失。 - 没有建立套接字描述符到对应
CLIENT结构体的映射关系,select遍历到就绪的客户端套接字时,无法匹配到该客户端对应的加密上下文。 - 握手逻辑为阻塞实现:
accept新客户端后直接调用connection_and_servicing进入握手死循环,在当前客户端握手完成前,服务端无法处理其他客户端的连接、消息请求,完全违背了select异步多路复用的设计初衷。 salt_init_session传入的握手缓冲区hndsk_buffer是connection_and_servicing函数的局部栈变量,函数返回后该空间会被回收,后续salt_channel访问该地址属于非法内存访问,会导致加密解密逻辑异常、程序崩溃等问题。
修复方案
- 新增数组或链表存储所有已接入的
CLIENT结构体实例,不要只用单个指针覆盖存储。 - 建立套接字值到
CLIENT实例的映射,比如可以用固定大小的数组(Windows下套接字值一般不会太大),或者遍历链表匹配sock_fd字段,在select遍历到就绪的客户端套接字时,先查找到对应的CLIENT实例再进行读写操作。 - 改写握手逻辑为非阻塞实现:将握手状态存储到
CLIENT结构体中,每次select检测到该客户端套接字可读时,再调用一次salt_handshake,直到握手完成或出错,不要在accept阶段阻塞等待握手完成。 - 将握手缓冲区
hndsk_buffer改为CLIENT结构体的成员变量,保证其生命周期和对应客户端的连接生命周期一致,避免栈内存释放后非法访问。 - 客户端连接断开时,要及时从
masterfd_set中移除对应套接字,同时释放对应的CLIENT结构体内存,避免内存泄漏和无效套接字误判。
内容的提问来源于stack exchange,提问作者cryptoTuke
相关产品推荐
相关产品推荐

