/* * 模块名称:Network Select Implementation * 模块功能:I/O 多路复用实现,包�?select �?poll 模式�? * 用于同时监控多个 Socket 的读写事�? * 适用平台:STM32F4 系列(CH395F 以太网芯片) * 作者:王建�? * 创建日期�?026-07-18 * 修改记录�? */ #include "net_select.h" #include "net_socket.h" #include "ch395f.h" /* * 私有函数声明�? */ static int check_socket_readable(int sockfd); static int check_socket_writable(int sockfd); static int check_socket_error(int sockfd); /* * 公共函数实现�? */ /* * 函数功能:I/O 多路复用(select 模式�? */ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds, net_fd_set *exceptfds, net_timeval *timeout) { uint32_t start_tick; uint32_t timeout_ms = 0; net_fd_set result_read = {0}; net_fd_set result_write = {0}; net_fd_set result_except = {0}; int ready_count = 0; int i; /* 计算超时时间 */ if (timeout != NULL) { timeout_ms = (uint32_t)(timeout->tv_sec * 1000) + (uint32_t)(timeout->tv_usec / 1000); } start_tick = HAL_GetTick(); while (1) { /* 轮询所�?Socket */ net_poll(); ready_count = 0; /* 检查哪�?Socket 有事�?*/ for (i = 0; i < nfds && i < NET_MAX_SOCKETS; i++) { net_sock_t *p_sock = net_get_sock(i); if (p_sock == NULL) { continue; } /* 检查可读事�?*/ if (readfds != NULL && NET_FD_ISSET(i, readfds)) { if (check_socket_readable(i)) { NET_FD_SET(i, &result_read); ready_count++; } } /* 检查可写事�?*/ if (writefds != NULL && NET_FD_ISSET(i, writefds)) { if (check_socket_writable(i)) { NET_FD_SET(i, &result_write); ready_count++; } } /* 检查异常事�?*/ if (exceptfds != NULL && NET_FD_ISSET(i, exceptfds)) { if (check_socket_error(i)) { NET_FD_SET(i, &result_except); ready_count++; } } } /* 有事件就绪,返回 */ if (ready_count > 0) { break; } /* 超时检�?*/ if (timeout != NULL) { if (timeout_ms > 0 && (HAL_GetTick() - start_tick) >= timeout_ms) { break; /* 超时返回 0 */ } } /* 短暂延时避免忙等 */ HAL_Delay(NET_POLL_DELAY_MS); } /* 复制结果 */ if (readfds != NULL) { readfds->fd_bits = result_read.fd_bits; } if (writefds != NULL) { writefds->fd_bits = result_write.fd_bits; } if (exceptfds != NULL) { exceptfds->fd_bits = result_except.fd_bits; } return ready_count; } /* * 函数功能:I/O 多路复用(poll 模式�? */ int net_poll_events(net_pollfd *fds, int nfds, int timeout) { uint32_t start_tick; int ready = 0; int i; if (fds == NULL || nfds <= 0) { return -1; } start_tick = HAL_GetTick(); while (1) { /* 轮询 */ net_poll(); ready = 0; for (i = 0; i < nfds; i++) { fds[i].revents = 0; /* 检�?fd 有效�?*/ if (fds[i].fd < 0 || fds[i].fd >= NET_MAX_SOCKETS) { fds[i].revents |= NET_POLLNVAL; ready++; continue; } net_sock_t *p_sock = net_get_sock(fds[i].fd); if (p_sock == NULL) { fds[i].revents |= NET_POLLNVAL; ready++; continue; } /* 检查可�?*/ if (fds[i].events & NET_POLLIN) { if (check_socket_readable(fds[i].fd)) { fds[i].revents |= NET_POLLIN; ready++; } } /* 检查可�?*/ if (fds[i].events & NET_POLLOUT) { if (check_socket_writable(fds[i].fd)) { fds[i].revents |= NET_POLLOUT; ready++; } } /* 检查错�?*/ if (check_socket_error(fds[i].fd)) { fds[i].revents |= NET_POLLERR; ready++; } /* 检查挂起(连接断开�?*/ if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT || p_sock->state == NET_SOCK_STATE_CLOSED) { fds[i].revents |= NET_POLLHUP; ready++; } } if (ready > 0) { break; } /* 超时检�?*/ if (timeout >= 0) { if ((HAL_GetTick() - start_tick) >= (uint32_t)timeout) { break; } } HAL_Delay(NET_POLL_DELAY_MS); } return ready; } /* * 私有函数实现�? */ /* * 函数功能:检�?Socket 是否可读 * 返回值:1 可读�? 不可�? */ static int check_socket_readable(int sockfd) { net_sock_t *p_sock; uint16_t recv_len; p_sock = net_get_sock(sockfd); if (p_sock == NULL) { return 0; } /* 监听 Socket 有新连接时可�?*/ if (p_sock->state == NET_SOCK_STATE_LISTENING) { return 1; } /* 已建立连接的 Socket 有数据可�?*/ if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) { recv_len = ch395f_get_recv_len(sockfd); if (recv_len > 0) { return 1; } } return 0; } /* * 函数功能:检�?Socket 是否可写 * 返回值:1 可写�? 不可�? */ static int check_socket_writable(int sockfd) { net_sock_t *p_sock; p_sock = net_get_sock(sockfd); if (p_sock == NULL) { return 0; } /* 已建立连接的 Socket 发送缓冲区空闲时可�?*/ if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) { if (p_sock->send_ready) { return 1; } } return 0; } /* * 函数功能:检�?Socket 是否有错�? * 返回值:1 有错误,0 无错�? */ static int check_socket_error(int sockfd) { net_sock_t *p_sock; /* 无效 fd 视为错误 */ if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) { return 1; } p_sock = net_get_sock(sockfd); if (p_sock == NULL) { return 1; /* 未使用的 Socket 视为错误 */ } return 0; }