Files
STM32F4-Base/Drivers/BSP/NET/net_select.c
2026-07-19 15:27:49 +08:00

263 lines
6.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称Network Select Implementation
* 模块功能I/O 多路复用实现<EFBC8C>?select <20>?poll 模式<E6A8A1>? * 用于同时监控多个 Socket 的读写事<E58699>? * 适用平台STM32F4 系列CH395F 以太网芯片)
* 作者王建<E78E8B>? * 创建日期<E697A5>?026-07-18
* 修改记录<E8AEB0>? */
#include "net_select.h"
#include "net_socket.h"
#include "ch395f.h"
/*
* 私有函数声明<E5A3B0>? */
static int check_socket_readable(int sockfd);
static int check_socket_writable(int sockfd);
static int check_socket_error(int sockfd);
/*
* 公共函数实现<E5AE9E>? */
/*
* 函数功能I/O 多路复用select 模式<E6A8A1>? */
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) {
/* 轮询所<E8AFA2>?Socket */
net_poll();
ready_count = 0;
/* 检查哪<E69FA5>?Socket 有事<E69C89>?*/
for (i = 0; i < nfds && i < NET_MAX_SOCKETS; i++) {
net_sock_t *p_sock = net_get_sock(i);
if (p_sock == NULL) {
continue;
}
/* 检查可读事<E8AFBB>?*/
if (readfds != NULL && NET_FD_ISSET(i, readfds)) {
if (check_socket_readable(i)) {
NET_FD_SET(i, &result_read);
ready_count++;
}
}
/* 检查可写事<E58699>?*/
if (writefds != NULL && NET_FD_ISSET(i, writefds)) {
if (check_socket_writable(i)) {
NET_FD_SET(i, &result_write);
ready_count++;
}
}
/* 检查异常事<E5B8B8>?*/
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;
}
/* 超时检<E697B6>?*/
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 模式<E6A8A1>? */
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 有效<E69C89>?*/
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;
}
/* 检查可<E69FA5>?*/
if (fds[i].events & NET_POLLIN) {
if (check_socket_readable(fds[i].fd)) {
fds[i].revents |= NET_POLLIN;
ready++;
}
}
/* 检查可<E69FA5>?*/
if (fds[i].events & NET_POLLOUT) {
if (check_socket_writable(fds[i].fd)) {
fds[i].revents |= NET_POLLOUT;
ready++;
}
}
/* 检查错<E69FA5>?*/
if (check_socket_error(fds[i].fd)) {
fds[i].revents |= NET_POLLERR;
ready++;
}
/* 检查挂起连接断开<E696AD>?*/
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;
}
/* 超时检<E697B6>?*/
if (timeout >= 0) {
if ((HAL_GetTick() - start_tick) >= (uint32_t)timeout) {
break;
}
}
HAL_Delay(NET_POLL_DELAY_MS);
}
return ready;
}
/*
* 私有函数实现<E5AE9E>? */
/*
* 函数功能<EFBC9A>?Socket 是否可读
* 返回值1 可读<E58FAF>? 不可<E4B88D>? */
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 有新连接时可<E697B6>?*/
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
return 1;
}
/* 已建立连接的 Socket 有数据可<E68DAE>?*/
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
recv_len = ch395f_get_recv_len(sockfd);
if (recv_len > 0) {
return 1;
}
}
return 0;
}
/*
* 函数功能<EFBC9A>?Socket 是否可写
* 返回值1 可写<E58FAF>? 不可<E4B88D>? */
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 发送缓冲区空闲时可<E697B6>?*/
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
if (p_sock->send_ready) {
return 1;
}
}
return 0;
}
/*
* 函数功能<EFBC9A>?Socket 是否有错<E69C89>? * 返回值1 有错误0 无错<E697A0>? */
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;
}