修改网络的初始化,异步支持问题
This commit is contained in:
@@ -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. 多连接模式下,先为数据 Socket(NET_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 已绑定且为 TCP;netTask 上下文
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; /* 累计发送字节数 */
|
||||
|
||||
Reference in New Issue
Block a user