修改网络的初始化,异步支持问题

This commit is contained in:
2026-07-21 01:22:09 +08:00
parent fbe0726991
commit f50b9c9e66
7 changed files with 337 additions and 138 deletions

View File

@@ -66,6 +66,7 @@ static void parse_ip_string(const char *str, uint8_t *ip_arr);
static int net_send_locked(net_sock_t *p_sock, const void *buf, int len);
static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags);
static int net_close_locked(net_sock_t *p_sock);
static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen);
/*
* 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式)
@@ -333,6 +334,17 @@ void net_process_messages(void) {
msg.addrlen);
break;
}
case NET_MSG_LISTEN: {
msg.result = net_listen_locked(msg.sockfd, msg.flags);
break;
}
case NET_MSG_ACCEPT: {
struct net_sockaddr *p_addr = (struct net_sockaddr *)msg.buf;
int addrlen = msg.len;
int *p_addrlen = (p_addr != NULL && addrlen > 0) ? &addrlen : NULL;
msg.result = net_accept_locked(msg.sockfd, p_addr, p_addrlen);
break;
}
default:
msg.result = -1;
break;
@@ -437,10 +449,11 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
ch395f_set_des_port((uint8_t)sockfd, 0);
status = ch395f_open_socket((uint8_t)sockfd);
if (status != CH395F_ERR_SUCCESS) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
if (status != CH395F_ERR_SUCCESS) {
DBG_ERROR("sock%d open_socket FAIL: status=0x%02X (expected 0x00)", sockfd, status);
s_net_errno = NET_ERR_BUSY;
return -1;
}
p_sock->state = NET_SOCK_STATE_UDP_OPEN;
} else {
@@ -451,27 +464,16 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
}
/*
* 函数功能:启动 TCP Server 监听(多连接模式
* 入口参数sockfd - Socket 描述符 (0~7),必须为已绑定的 TCP Socket int
* backlog - 最大并发数据 Socket 数量 int >= 1
* 返回值0 - 监听启动成功 int
* -1 - 监听失败(参数无效、状态错误等) int
* 限定条件Socket 已通过 net_socket() + net_bind() 创建并绑定type == NET_SOCK_STREAM
* 函数说明1. 多连接模式下,先为数据 SocketNET_TCP_SERVER_DATA_SOCK_START ~ 7配置协议类型、源端口和独立缓冲区
* 2. CH395F 根据源端口匹配、协议类型为 TCP、状态为 CLOSED 查找可用 Socket 进行自动分配
* 3. 最后配置监听 Socket 并启动 TCP_LISTEN
* 函数功能:启动 TCP Server 监听(内部版本,必须在 netTask 上下文调用
* 入口参数sockfd - Socket 描述符 (0~7) int
* backlog - 数据 Socket 数量0=单连接模式) int
* 返回值0 - 成功,-1 - 失败 int
* 限定条件sockfd 已绑定且为 TCPnetTask 上下文
*/
int net_listen(int sockfd, int backlog) {
net_sock_t *p_sock;
int net_listen_locked(int sockfd, int backlog) {
net_sock_t *p_sock = &s_net_socks[sockfd];
uint8_t status;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
p_sock = &s_net_socks[sockfd];
if (!p_sock->in_use || p_sock->type != NET_SOCK_STREAM) {
s_net_errno = NET_ERR_INVAL;
return -1;
@@ -483,25 +485,29 @@ int net_listen(int sockfd, int backlog) {
return -1;
}
/* 多连接模式:先为数据 Socket 设置协议类型、源端口和独立缓冲区。
* 必须在监听 Socket OPEN+LISTEN 之前配置,确保 CH395F
* 自动分配机制能扫描到所有可用 Socket。
* CH395F 根据源端口匹配、协议类型为 TCP、状态为 CLOSED 查找可用 Socket。 */
for (int ds = NET_TCP_SERVER_DATA_SOCK_START; ds < NET_MAX_SOCKETS; ds++) {
uint8_t base = (uint8_t)(ds * 4);
ch395f_set_send_buf((uint8_t)ds, base, 2);
ch395f_set_recv_buf((uint8_t)ds, base + 2, 2);
/* <20>?CH395F 手册 9.2.6 节顺序:先设源端口,再设协议类型 */
ch395f_set_sour_port((uint8_t)ds, p_sock->local_port);
ch395f_set_proto_type((uint8_t)ds, CH395F_PROTO_TYPE_TCP);
s_net_socks[ds].in_use = 1;
s_net_socks[ds].state = NET_SOCK_STATE_TCP_ACCEPT;
s_net_socks[ds].type = NET_SOCK_STREAM;
s_net_socks[ds].ch395_sock = (uint8_t)ds;
s_net_socks[ds].send_ready = 1;
/* 多连接模式:按 backlog 分配数据 Socket */
if (backlog > 0) {
int max_ds = NET_TCP_SERVER_DATA_SOCK_START + backlog;
if (max_ds > NET_MAX_SOCKETS) {
max_ds = NET_MAX_SOCKETS;
}
for (int ds = NET_TCP_SERVER_DATA_SOCK_START; ds < max_ds; ds++) {
uint8_t base = (uint8_t)(ds * 4);
ch395f_set_send_buf((uint8_t)ds, base, 2);
ch395f_set_recv_buf((uint8_t)ds, base + 2, 2);
ch395f_set_sour_port((uint8_t)ds, p_sock->local_port);
ch395f_set_proto_type((uint8_t)ds, CH395F_PROTO_TYPE_TCP);
s_net_socks[ds].in_use = 1;
s_net_socks[ds].state = NET_SOCK_STATE_TCP_ACCEPT;
s_net_socks[ds].type = NET_SOCK_STREAM;
s_net_socks[ds].ch395_sock = (uint8_t)ds;
s_net_socks[ds].send_ready = 1;
p_sock->data_socks[p_sock->data_sock_count++] = ds;
}
}
/* 最后配置监<EFBFBD>?Socket 并启动监<EFBFBD>?*/
/* 配置监Socket */
ch395f_set_send_buf((uint8_t)sockfd, 0, 2);
ch395f_set_recv_buf((uint8_t)sockfd, 2, 2);
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
@@ -513,10 +519,12 @@ int net_listen(int sockfd, int backlog) {
return -1;
}
/* 启动 TCP 监听 */
ch395f_tcp_listen(sockfd);
p_sock->state = NET_SOCK_STATE_LISTENING;
if (backlog == 0) {
p_sock->standalone_accept = 1;
}
for (int j = 0; j < NET_MAX_SOCKETS; j++) {
(void)ch395f_get_sock_int_status((uint8_t)j);
@@ -527,39 +535,72 @@ int net_listen(int sockfd, int backlog) {
}
/*
* 函数功能TCP Server 接受新连接,返回已建立连接的 Socket 描述符
* 入口参数sockfd - 监听 Socket 描述符 int
* addr - 输出:客户端地址结构体指针 struct net_sockaddr *(可为 NULL
* addrlen - 输入输出:地址结构体长度 int *(可为 NULL
* 返回值:新连接的 Socket 描述符 (1~7),失败返回 -1 int >= 0 || -1
* 限定条件Socket 处于 LISTENING 状态net_poll() 已检测到 CONNECT 事件
* 函数说明:遍历所有数据 Socket查找与客户端地址匹配且已建立连接ESTABLISHED的 Socket
* 函数功能:启动 TCP Server 监听(线程安全版本,通过消息队列委托给 netTask
* 入口参数sockfd - Socket 描述符 int
* backlog - 数据 Socket 数量 int
* 返回值0 - 成功,-1 - 失败 int
* 限定条件net_init() + MX_FREERTOS_Init() 已执行;必须在任务上下文中调用
* 函数说明:通过消息队列委托给 netTask确保 SPI 串行化
*/
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
net_sock_t *p_listen_sock;
int i;
int net_listen(int sockfd, int backlog) {
net_msg_t msg;
/* 参数检<E695B0>?*/
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
if (netMsgQueueHandle == NULL) {
s_net_errno = NET_ERR;
return -1;
}
msg.type = NET_MSG_LISTEN;
msg.sockfd = sockfd;
msg.flags = backlog;
msg.caller = xTaskGetCurrentTaskHandle();
msg.result = -1;
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
if (msg.result < 0) {
s_net_errno = NET_ERR;
}
return msg.result;
}
/*
* 函数功能TCP Server 接受新连接(内部版本,必须在 netTask 上下文调用)
* 入口参数sockfd - 监听 Socket 描述符 int
* addr - 输出:客户端地址结构体指针 struct net_sockaddr *(可为 NULL
* addrlen - 输入输出:地址结构体长度 int *(可为 NULL
* 返回值:新连接的 Socket 描述符,失败返回 -1 int
* 限定条件Socket 处于 LISTENING 状态
* 函数说明:先查 data_socks[] 多连接数据 Socket再查 standalone_accept 单连接 Socket
*/
static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen) {
net_sock_t *p_listen_sock;
int i;
p_listen_sock = &s_net_socks[sockfd];
if (!p_listen_sock->in_use || p_listen_sock->state != NET_SOCK_STATE_LISTENING) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
/* 轮询查找已建立连接的数据 Socket */
net_poll();
/* 多连接模式:查 data_socks */
for (i = 0; i < p_listen_sock->data_sock_count; i++) {
int data_sock = p_listen_sock->data_socks[i];
net_sock_t *p_data_cb = &s_net_socks[data_sock];
if (p_data_cb->state == NET_SOCK_STATE_ESTABLISHED) {
/* 找到已建立连接的 Socket */
if (addr != NULL && addrlen != NULL) {
struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)addr;
p_addr_in->sin_family = NET_AF_INET;
@@ -567,16 +608,73 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
p_addr_in->sin_addr.s_addr = p_data_cb->remote_ip;
*addrlen = sizeof(struct net_sockaddr_in);
}
return data_sock;
}
}
/* 没有新连<EFBFBD>?*/
/* 单连接模式PASV查 standalone 监听者是否已 ESTABLISHED */
if (p_listen_sock->standalone_accept &&
p_listen_sock->state == NET_SOCK_STATE_ESTABLISHED) {
if (addr != NULL && addrlen != NULL) {
struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)addr;
p_addr_in->sin_family = NET_AF_INET;
p_addr_in->sin_port = net_htons(p_listen_sock->remote_port);
p_addr_in->sin_addr.s_addr = p_listen_sock->remote_ip;
*addrlen = sizeof(struct net_sockaddr_in);
}
return sockfd;
}
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
}
/*
* 函数功能TCP Server 接受新连接(线程安全版本,通过消息队列委托给 netTask
* 入口参数sockfd - 监听 Socket 描述符 int
* addr - 输出:客户端地址结构体指针 struct net_sockaddr *(可为 NULL
* addrlen - 输入输出:地址结构体长度 int *(可为 NULL
* 返回值:新连接的 Socket 描述符,失败返回 -1 int
* 限定条件Socket 处于 LISTENING 状态net_init() + MX_FREERTOS_Init() 已执行;非 netTask 上下文
* 函数说明:将接受请求放入消息队列,阻塞等待 netTask 处理完毕
*/
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
net_msg_t msg;
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
s_net_errno = NET_ERR_BADF;
return -1;
}
if (netMsgQueueHandle == NULL) {
s_net_errno = NET_ERR;
return -1;
}
msg.type = NET_MSG_ACCEPT;
msg.sockfd = sockfd;
msg.buf = (void *)addr;
msg.len = (addrlen != NULL) ? *addrlen : 0;
msg.caller = xTaskGetCurrentTaskHandle();
msg.result = -1;
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
if (addrlen != NULL && addr != NULL) {
*addrlen = sizeof(struct net_sockaddr_in);
}
if (msg.result < 0) {
s_net_errno = NET_ERR;
}
return msg.result;
}
/*
* 函数功能TCP Client 发起与服务器的连接
* 入口参数sockfd - Socket 描述符 (0~7),必须为已创建的 TCP Socket int

View File

@@ -27,6 +27,8 @@ typedef enum {
NET_MSG_RECV,
NET_MSG_CLOSE,
NET_MSG_CONNECT,
NET_MSG_LISTEN,
NET_MSG_ACCEPT,
} net_msg_type_t;
typedef struct {
@@ -318,6 +320,15 @@ int net_recv_sock(net_sock_t *p_sock, void *buf, int len, int flags);
*/
int net_close_sock(net_sock_t *p_sock);
/*
* 函数功能:启动 TCP Server 监听(内部版本,直接操作,不经过消息队列)
* 入口参数sockfd - Socket 描述符
* backlog - 数据 Socket 数量0=单连接模式)
* 返回值0 成功,-1 失败
* 限定条件:必须在 netTask 上下文中调用
*/
int net_listen_locked(int sockfd, int backlog);
#ifdef __cplusplus
}
#endif

View File

@@ -163,6 +163,9 @@ typedef struct {
/* 发送就绪标志 */
uint8_t send_ready;
/* 独立监听标志PASV 用):该 Socket 为独立监听者,收到 CONNECT 后转为 ESTABLISHED断开后释放 */
uint8_t standalone_accept;
/* 统计信息 */
uint32_t recv_bytes; /* 累计接收字节数 */
uint32_t send_bytes; /* 累计发送字节数 */