修复多连接的问题
This commit is contained in:
@@ -1,34 +1,26 @@
|
||||
/*
|
||||
* 模块名称:Network Select Implementation
|
||||
* 模块功能:I/O 多路复用实现,包括 select 和 poll 模式,
|
||||
* 用于同时监控多个 Socket 的读写事件
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
*/
|
||||
* 模块功能:I/O 多路复用实现,包<EFBFBD>?select <EFBFBD>?poll 模式<EFBFBD>? * 用于同时监控多个 Socket 的读写事<E58699>? * 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建<EFBFBD>? * 创建日期<E697A5>?026-07-18
|
||||
* 修改记录<EFBFBD>? */
|
||||
|
||||
#include "net_select.h"
|
||||
#include "net_socket.h"
|
||||
#include "ch395f.h"
|
||||
|
||||
/*
|
||||
* 私有函数声明区
|
||||
*/
|
||||
* 私有函数声明<EFBFBD>? */
|
||||
static int check_socket_readable(int sockfd);
|
||||
static int check_socket_writable(int sockfd);
|
||||
static int check_socket_error(int sockfd);
|
||||
|
||||
/*
|
||||
* 公共函数实现区
|
||||
*/
|
||||
* 公共函数实现<EFBFBD>? */
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(select 模式)
|
||||
*/
|
||||
* 函数功能:I/O 多路复用(select 模式<EFBFBD>? */
|
||||
int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
net_fd_set *exceptfds, net_timeval *timeout)
|
||||
{
|
||||
net_fd_set *exceptfds, net_timeval *timeout) {
|
||||
uint32_t start_tick;
|
||||
uint32_t timeout_ms = 0;
|
||||
net_fd_set result_read = {0};
|
||||
@@ -38,56 +30,46 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
int i;
|
||||
|
||||
/* 计算超时时间 */
|
||||
if (timeout != NULL)
|
||||
{
|
||||
if (timeout != NULL) {
|
||||
timeout_ms = (uint32_t)(timeout->tv_sec * 1000) +
|
||||
(uint32_t)(timeout->tv_usec / 1000);
|
||||
}
|
||||
|
||||
start_tick = HAL_GetTick();
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 轮询所有 Socket */
|
||||
while (1) {
|
||||
/* 轮询所<E8AFA2>?Socket */
|
||||
net_poll();
|
||||
|
||||
ready_count = 0;
|
||||
|
||||
/* 检查哪些 Socket 有事件 */
|
||||
for (i = 0; i < nfds && i < NET_MAX_SOCKETS; i++)
|
||||
{
|
||||
net_sock_t *sock = net_get_sock(i);
|
||||
/* 检查哪<EFBFBD>?Socket 有事<EFBFBD>?*/
|
||||
for (i = 0; i < nfds && i < NET_MAX_SOCKETS; i++) {
|
||||
net_sock_t *p_sock = net_get_sock(i);
|
||||
|
||||
if (sock == NULL)
|
||||
{
|
||||
if (p_sock == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 检查可读事件 */
|
||||
if (readfds != NULL && NET_FD_ISSET(i, readfds))
|
||||
{
|
||||
if (check_socket_readable(i))
|
||||
{
|
||||
/* 检查可读事<EFBFBD>?*/
|
||||
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))
|
||||
{
|
||||
/* 检查可写事<EFBFBD>?*/
|
||||
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))
|
||||
{
|
||||
/* 检查异常事<EFBFBD>?*/
|
||||
if (exceptfds != NULL && NET_FD_ISSET(i, exceptfds)) {
|
||||
if (check_socket_error(i)) {
|
||||
NET_FD_SET(i, &result_except);
|
||||
ready_count++;
|
||||
}
|
||||
@@ -95,17 +77,14 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
}
|
||||
|
||||
/* 有事件就绪,返回 */
|
||||
if (ready_count > 0)
|
||||
{
|
||||
if (ready_count > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 超时检查 */
|
||||
if (timeout != NULL)
|
||||
{
|
||||
/* 超时检<EFBFBD>?*/
|
||||
if (timeout != NULL) {
|
||||
if (timeout_ms > 0 &&
|
||||
(HAL_GetTick() - start_tick) >= timeout_ms)
|
||||
{
|
||||
(HAL_GetTick() - start_tick) >= timeout_ms) {
|
||||
break; /* 超时返回 0 */
|
||||
}
|
||||
}
|
||||
@@ -115,16 +94,13 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
}
|
||||
|
||||
/* 复制结果 */
|
||||
if (readfds != NULL)
|
||||
{
|
||||
if (readfds != NULL) {
|
||||
readfds->fd_bits = result_read.fd_bits;
|
||||
}
|
||||
if (writefds != NULL)
|
||||
{
|
||||
if (writefds != NULL) {
|
||||
writefds->fd_bits = result_write.fd_bits;
|
||||
}
|
||||
if (exceptfds != NULL)
|
||||
{
|
||||
if (exceptfds != NULL) {
|
||||
exceptfds->fd_bits = result_except.fd_bits;
|
||||
}
|
||||
|
||||
@@ -132,95 +108,79 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(poll 模式)
|
||||
*/
|
||||
int net_poll_events(net_pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
* 函数功能:I/O 多路复用(poll 模式<EFBFBD>? */
|
||||
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)
|
||||
{
|
||||
if (fds == NULL || nfds <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
start_tick = HAL_GetTick();
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
/* 轮询 */
|
||||
net_poll();
|
||||
|
||||
ready = 0;
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
for (i = 0; i < nfds; i++) {
|
||||
fds[i].revents = 0;
|
||||
|
||||
/* 检查 fd 有效性 */
|
||||
if (fds[i].fd < 0 || fds[i].fd >= NET_MAX_SOCKETS)
|
||||
{
|
||||
/* 检<EFBFBD>?fd 有效<EFBFBD>?*/
|
||||
if (fds[i].fd < 0 || fds[i].fd >= NET_MAX_SOCKETS) {
|
||||
fds[i].revents |= NET_POLLNVAL;
|
||||
ready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
net_sock_t *sock = net_get_sock(fds[i].fd);
|
||||
net_sock_t *p_sock = net_get_sock(fds[i].fd);
|
||||
|
||||
if (sock == NULL)
|
||||
{
|
||||
if (p_sock == NULL) {
|
||||
fds[i].revents |= NET_POLLNVAL;
|
||||
ready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 检查可读 */
|
||||
if (fds[i].events & NET_POLLIN)
|
||||
{
|
||||
if (check_socket_readable(fds[i].fd))
|
||||
{
|
||||
/* 检查可<EFBFBD>?*/
|
||||
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))
|
||||
{
|
||||
/* 检查可<EFBFBD>?*/
|
||||
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))
|
||||
{
|
||||
/* 检查错<EFBFBD>?*/
|
||||
if (check_socket_error(fds[i].fd)) {
|
||||
fds[i].revents |= NET_POLLERR;
|
||||
ready++;
|
||||
}
|
||||
|
||||
/* 检查挂起(连接断开) */
|
||||
if (sock->state == NET_SOCK_STATE_TCP_ACCEPT ||
|
||||
sock->state == NET_SOCK_STATE_CLOSED)
|
||||
{
|
||||
/* 检查挂起(连接断开<EFBFBD>?*/
|
||||
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)
|
||||
{
|
||||
if (ready > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 超时检查 */
|
||||
if (timeout >= 0)
|
||||
{
|
||||
if ((HAL_GetTick() - start_tick) >= (uint32_t)timeout)
|
||||
{
|
||||
/* 超时检<EFBFBD>?*/
|
||||
if (timeout >= 0) {
|
||||
if ((HAL_GetTick() - start_tick) >= (uint32_t)timeout) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -232,36 +192,29 @@ int net_poll_events(net_pollfd *fds, int nfds, int timeout)
|
||||
}
|
||||
|
||||
/*
|
||||
* 私有函数实现区
|
||||
*/
|
||||
* 私有函数实现<EFBFBD>? */
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否可读
|
||||
* 返回值:1 可读,0 不可读
|
||||
*/
|
||||
static int check_socket_readable(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
* 函数功能:检<EFBFBD>?Socket 是否可读
|
||||
* 返回值:1 可读<EFBFBD>? 不可<EFBFBD>? */
|
||||
static int check_socket_readable(int sockfd) {
|
||||
net_sock_t *p_sock;
|
||||
uint16_t recv_len;
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
p_sock = net_get_sock(sockfd);
|
||||
if (p_sock == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 监听 Socket 有新连接时可读 */
|
||||
if (sock->state == NET_SOCK_STATE_LISTENING)
|
||||
{
|
||||
/* 监听 Socket 有新连接时可<EFBFBD>?*/
|
||||
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 已建立连接的 Socket 有数据可读 */
|
||||
if (sock->state == NET_SOCK_STATE_ESTABLISHED)
|
||||
{
|
||||
/* 已建立连接的 Socket 有数据可<EFBFBD>?*/
|
||||
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
|
||||
recv_len = ch395f_get_recv_len(sockfd);
|
||||
if (recv_len > 0)
|
||||
{
|
||||
if (recv_len > 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -270,24 +223,19 @@ static int check_socket_readable(int sockfd)
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否可写
|
||||
* 返回值:1 可写,0 不可写
|
||||
*/
|
||||
static int check_socket_writable(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
* 函数功能:检<EFBFBD>?Socket 是否可写
|
||||
* 返回值:1 可写<EFBFBD>? 不可<EFBFBD>? */
|
||||
static int check_socket_writable(int sockfd) {
|
||||
net_sock_t *p_sock;
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
p_sock = net_get_sock(sockfd);
|
||||
if (p_sock == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 已建立连接的 Socket 发送缓冲区空闲时可写 */
|
||||
if (sock->state == NET_SOCK_STATE_ESTABLISHED)
|
||||
{
|
||||
if (sock->send_ready)
|
||||
{
|
||||
/* 已建立连接的 Socket 发送缓冲区空闲时可<EFBFBD>?*/
|
||||
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
|
||||
if (p_sock->send_ready) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -296,22 +244,17 @@ static int check_socket_writable(int sockfd)
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否有错误
|
||||
* 返回值:1 有错误,0 无错误
|
||||
*/
|
||||
static int check_socket_error(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
* 函数功能:检<EFBFBD>?Socket 是否有错<EFBFBD>? * 返回值:1 有错误,0 无错<E697A0>? */
|
||||
static int check_socket_error(int sockfd) {
|
||||
net_sock_t *p_sock;
|
||||
|
||||
/* 无效 fd 视为错误 */
|
||||
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS)
|
||||
{
|
||||
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
p_sock = net_get_sock(sockfd);
|
||||
if (p_sock == NULL) {
|
||||
return 1; /* 未使用的 Socket 视为错误 */
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,7 @@ int net_poll(void);
|
||||
* protocol - 通常为 0
|
||||
* 返回值:socket 描述符 (0~7),失败返回 -1
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:自动分配空闲 Socket 控制块
|
||||
*/
|
||||
int net_socket(int domain, int type, int protocol);
|
||||
|
||||
@@ -61,6 +62,8 @@ int net_socket(int domain, int type, int protocol);
|
||||
* addr - 本地地址结构体指针
|
||||
* addrlen - 地址结构体长度
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:socket 已创建且未绑定
|
||||
* 函数说明:设置 CH395F 源端口
|
||||
*/
|
||||
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
|
||||
@@ -70,6 +73,7 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
* backlog - 最大等待连接数(多连接模式下为数据 Socket 数量)
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:socket 已绑定
|
||||
* 函数说明:内部调用 ch395f_tcp_listen,多连接模式自动配置数据 Socket
|
||||
*/
|
||||
int net_listen(int sockfd, int backlog);
|
||||
|
||||
@@ -104,7 +108,8 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
* len - 数据长度
|
||||
* flags - 通常为 0
|
||||
* 返回值:实际发送字节数,失败返回 -1
|
||||
* 限定条件:TCP 连接已建立
|
||||
* 限定条件:TCP 连接已建立,指针非空
|
||||
* 函数说明:阻塞等待发送缓冲区空闲,拷贝数据后触发发送
|
||||
*/
|
||||
int net_send(int sockfd, const void *buf, int len, int flags);
|
||||
|
||||
@@ -124,13 +129,15 @@ int net_recv(int sockfd, void *buf, int len, int flags);
|
||||
|
||||
/*
|
||||
* 函数功能:发送 UDP 数据
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* buf - 数据缓冲区
|
||||
* len - 数据长度
|
||||
* flags - 通常为 0
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* buf - 数据缓冲区
|
||||
* len - 数据长度
|
||||
* flags - 通常为 0
|
||||
* dest_addr - 目标地址
|
||||
* addrlen - 地址长度
|
||||
* addrlen - 地址长度
|
||||
* 返回值:实际发送字节数,失败返回 -1
|
||||
* 限定条件:socket 已创建,指针非空
|
||||
* 函数说明:设置目标地址后调用 CH395F 发送
|
||||
*/
|
||||
int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
const struct net_sockaddr *dest_addr, int addrlen);
|
||||
@@ -144,6 +151,8 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
* src_addr - 输出:发送方地址
|
||||
* addrlen - 输入输出:地址长度
|
||||
* 返回值:实际接收字节数,失败返回 -1
|
||||
* 限定条件:socket 已创建,指针非空
|
||||
* 函数说明:读取 CH395F 接收缓冲区,获取对端地址
|
||||
*/
|
||||
int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
struct net_sockaddr *src_addr, int *addrlen);
|
||||
@@ -152,6 +161,8 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
* 函数功能:关闭 socket
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:socket 已打开
|
||||
* 函数说明:释放 Socket 控制块,TCP 先断开连接
|
||||
*/
|
||||
int net_close(int sockfd);
|
||||
|
||||
@@ -165,6 +176,8 @@ int net_close(int sockfd);
|
||||
* cb - 回调函数
|
||||
* arg - 用户参数
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:socket 已创建
|
||||
* 函数说明:回调在 net_poll 上下文中触发
|
||||
*/
|
||||
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg);
|
||||
|
||||
@@ -181,7 +194,9 @@ int net_get_errno(void);
|
||||
/*
|
||||
* 函数功能:将 IP 地址字符串转为网络字节序
|
||||
* 入口参数:cp - 点分十进制字符串 "192.168.1.100"
|
||||
* 返回值:网络字节序 IP
|
||||
* 返回值:网络字节序 IP,失败返回 0
|
||||
* 限定条件:cp 指针非空
|
||||
* 函数说明:不支持域名解析
|
||||
*/
|
||||
uint32_t net_inet_addr(const char *cp);
|
||||
|
||||
@@ -190,26 +205,43 @@ uint32_t net_inet_addr(const char *cp);
|
||||
* 入口参数:addr - 网络字节序 IP
|
||||
* buf - 输出缓冲区(至少 16 字节)
|
||||
* 返回值:buf 指针
|
||||
* 限定条件:buf 指针非空
|
||||
*/
|
||||
char *net_inet_ntoa(uint32_t addr, char *buf);
|
||||
|
||||
/*
|
||||
* 函数功能:端口字节序转换(主机序 -> 网络序)
|
||||
* 入口参数:hostshort - 主机序端口
|
||||
* 返回值:网络序端口
|
||||
* 限定条件:无
|
||||
* 函数说明:小端 → 大端
|
||||
*/
|
||||
uint16_t net_htons(uint16_t hostshort);
|
||||
|
||||
/*
|
||||
* 函数功能:端口字节序转换(网络序 -> 主机序)
|
||||
* 入口参数:netshort - 网络序端口
|
||||
* 返回值:主机序端口
|
||||
* 限定条件:无
|
||||
* 函数说明:大端 → 小端
|
||||
*/
|
||||
uint16_t net_ntohs(uint16_t netshort);
|
||||
|
||||
/*
|
||||
* 函数功能:IP 地址字节序转换(主机序 -> 网络序)
|
||||
* 入口参数:hostlong - 主机序 IP
|
||||
* 返回值:网络序 IP
|
||||
* 限定条件:无
|
||||
* 函数说明:小端 → 大端
|
||||
*/
|
||||
uint32_t net_htonl(uint32_t hostlong);
|
||||
|
||||
/*
|
||||
* 函数功能:IP 地址字节序转换(网络序 -> 主机序)
|
||||
* 入口参数:netlong - 网络序 IP
|
||||
* 返回值:主机序 IP
|
||||
* 限定条件:无
|
||||
* 函数说明:大端 → 小端
|
||||
*/
|
||||
uint32_t net_ntohl(uint32_t netlong);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user