删除多连接内容,只支持单连接

This commit is contained in:
2026-08-25 12:41:33 +08:00
parent d6bc3f6253
commit 0a707034cc
10 changed files with 109 additions and 507 deletions

View File

@@ -29,7 +29,7 @@ int lftpd_inet_listen(int port)
return -1;
}
if (net_listen(s, 0) >= 0) {
if (net_listen(s) >= 0) {
return s;
}
@@ -43,34 +43,6 @@ int lftpd_inet_listen(int port)
return -1;
}
int lftpd_inet_listen_multi(int port, int backlog)
{
int s = net_socket(NET_AF_INET, NET_SOCK_STREAM, 0);
if (s < 0) {
DBG_ERROR("error creating multi listener socket");
return -1;
}
struct net_sockaddr_in addr;
addr.sin_family = NET_AF_INET;
addr.sin_port = net_htons((uint16_t)port);
addr.sin_addr.s_addr = 0;
if (net_bind(s, (struct net_sockaddr *)&addr, sizeof(addr)) < 0) {
DBG_ERROR("error binding multi listener port %d", port);
net_close(s);
return -1;
}
if (net_listen(s, backlog) < 0) {
DBG_ERROR("error listening on multi socket");
net_close(s);
return -1;
}
return s;
}
int lftpd_inet_get_socket_port(int socket)
{
struct net_sockaddr_in addr;

View File

@@ -4,7 +4,6 @@
#include <stdint.h>
int lftpd_inet_listen(int port);
int lftpd_inet_listen_multi(int port, int backlog);
int lftpd_inet_get_socket_port(int socket);
int lftpd_inet_accept(int socket);
int lftpd_inet_accept_timeout(int socket, int timeout_ms);

View File

@@ -30,14 +30,6 @@ extern "C" {
#define NET_TCP_SERVER_LISTEN_SOCK 0 /* 监听 Socket 索引 */
#endif
#ifndef NET_TCP_SERVER_DATA_SOCK_START
#define NET_TCP_SERVER_DATA_SOCK_START 1 /* 数据 Socket 起始索引 */
#endif
#ifndef NET_TCP_SERVER_MAX_CLIENTS
#define NET_TCP_SERVER_MAX_CLIENTS 7 /* 最大客户端数1~7 */
#endif
/*
* 缓冲区大小配置
*/

View File

@@ -209,8 +209,7 @@ int net_poll_events(net_pollfd *fds, int nfds, int timeout) {
}
/* 检查挂起(连接断开) */
if ((NET_SOCK_STATE_TCP_ACCEPT == p_sock->state) ||
(NET_SOCK_STATE_CLOSED == p_sock->state)) {
if (NET_SOCK_STATE_CLOSED == p_sock->state) {
fds[i].revents |= NET_POLLHUP;
ready++;
}

View File

@@ -313,7 +313,7 @@ void net_process_messages(void) {
break;
}
case NET_MSG_LISTEN: {
msg.result = net_listen_locked(msg.sockfd, msg.flags);
msg.result = net_listen_locked(msg.sockfd);
break;
}
case NET_MSG_ACCEPT: {
@@ -453,11 +453,10 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
/*
* 函数功能:启动 TCP Server 监听(内部版本,必须在 netTask 上下文调用)
* 入口参数sockfd - Socket 描述符 (0~7) int
* backlog - 数据 Socket 数量0=单连接模式) int
* 返回值0 - 成功,-1 - 失败 int
* 限定条件sockfd 已绑定且为 TCPnetTask 上下文
*/
int net_listen_locked(int sockfd, int backlog) {
int net_listen_locked(int sockfd) {
/* 取监听 Socket 控制块直接下标访问sockfd 已在上层 net_listen 校验过范围) */
net_sock_t *p_sock = &s_net_socks[sockfd];
/* CH395F 打开 Socket 的返回状态 */
@@ -476,46 +475,10 @@ int net_listen_locked(int sockfd, int backlog) {
return -1;
}
/* 多连接模式backlog > 0为数据 Socket 分配并初始化 CH395F 资源 */
if (backlog > 0) {
/* 数据 Socket 编号范围:[NET_TCP_SERVER_DATA_SOCK_START, max_ds) */
int max_ds = NET_TCP_SERVER_DATA_SOCK_START + backlog;
/* 越界保护:不超过 Socket 总数 */
if (max_ds > NET_MAX_SOCKETS) {
max_ds = NET_MAX_SOCKETS;
}
/* 逐个配置数据 Socket供后续 accept 时承接新连接 */
for (int ds = NET_TCP_SERVER_DATA_SOCK_START; ds < max_ds; ds++) {
/* 以 4 块为单位划出该 Socket 的发送/接收缓冲(发送占前 2 块,接收占后 2 块) */
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);
/* 数据 Socket 监听同一本地端口,协议类型为 TCP */
ch395f_set_sour_port((uint8_t)ds, p_sock->local_port);
ch395f_set_proto_type((uint8_t)ds, CH395F_PROTO_TYPE_TCP);
/* 登记数据 Socket 控制块:标记已用、等待连接态、流类型、绑定硬件 Socket 号 */
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;
/* 记录到监听 Socket 的数据 Socket 列表,供 net_accept_locked 查表 */
p_sock->data_socks[p_sock->data_sock_count++] = ds;
}
}
/*
* 配置监听 Socket 自身缓冲
* - 单连接模式backlog==0通常用 Socket 0~3CH395F 默认缓冲互不重叠,无需重设;
* - 多连接模式Socket 4~7 默认无收发缓冲):显式按 4 块划分发送/接收缓冲。
* 本实现仅支持单连接:监听 Socket 自身即为数据通道,复用 CH395F 默认收发缓冲
* Socket 0~3 默认缓冲互不重叠),不再为数据 Socket 额外分配。
*/
if (backlog > 0) {
uint8_t base = (uint8_t)(sockfd * 4);
ch395f_set_send_buf((uint8_t)sockfd, base, 2);
ch395f_set_recv_buf((uint8_t)sockfd, base + 2, 2);
}
/* 监听 Socket 协议类型为 TCP并绑定本地端口 */
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port(sockfd, p_sock->local_port);
@@ -533,16 +496,16 @@ int net_listen_locked(int sockfd, int backlog) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
/* 下发 TCP LISTEN 命令,进入监听状态 */
ch395f_tcp_listen(sockfd);
status = ch395f_tcp_listen(sockfd);
if (status != CH395F_ERR_SUCCESS) {
s_net_errno = NET_ERR_BUSY;
return -1;
}
/* 监听 Socket 进入 LISTENING 态 */
p_sock->state = NET_SOCK_STATE_LISTENING;
/* 单连接模式标记为 standalone_acceptCONNECT 中断直接作用于本 Socket 自身 */
if (backlog == 0) {
p_sock->standalone_accept = 1;
}
/* 单连接CONNECT 中断直接作用于本 Socket 自身 */
/*
* 启动监听前清空各 Socket 及全局中断状态寄存器(读即清除),
@@ -559,12 +522,11 @@ int net_listen_locked(int sockfd, int backlog) {
/*
* 函数功能:启动 TCP Server 监听(线程安全版本,通过消息队列委托给 netTask
* 入口参数sockfd - Socket 描述符 int
* backlog - 数据 Socket 数量 int
* 返回值0 - 成功,-1 - 失败 int
* 限定条件net_init() + MX_FREERTOS_Init() 已执行;必须在任务上下文中调用
* 函数说明:通过消息队列委托给 netTask确保 SPI 串行化
*/
int net_listen(int sockfd, int backlog) {
int net_listen(int sockfd) {
net_msg_t msg;
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
@@ -579,7 +541,6 @@ int net_listen(int sockfd, int backlog) {
msg.type = NET_MSG_LISTEN;
msg.sockfd = sockfd;
msg.flags = backlog;
msg.caller = xTaskGetCurrentTaskHandle();
msg.result = -1;
@@ -607,57 +568,37 @@ int net_listen(int sockfd, int backlog) {
* addrlen - 输入输出:地址结构体长度 int *(可为 NULL
* 返回值:新连接的 Socket 描述符,失败返回 -1 int
* 限定条件Socket 处于 LISTENING 状态
* 函数说明:先查 data_socks[] 多连接数据 Socket再查 standalone_accept 单连接 Socket
* 函数说明:单连接:监听 Socket 自身在 CONNECT 后已转为 ESTABLISHED
*/
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) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
if (p_listen_sock->state != NET_SOCK_STATE_LISTENING &&
!(p_listen_sock->standalone_accept && p_listen_sock->state == NET_SOCK_STATE_ESTABLISHED)) {
s_net_errno = NET_ERR_INVAL;
return -1;
}
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) {
if (NULL != addr &&NULL != addrlen) {
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_data_cb->remote_port);
p_addr_in->sin_addr.s_addr = p_data_cb->remote_ip;
*addrlen = sizeof(struct net_sockaddr_in);
}
return data_sock;
}
/* 连接:本 Socket 自身在 CONNECT 后已转为 ESTABLISHED
* 只有处于 ESTABLISHED 才表示有可接受的连接;否则尚无连接 */
if (p_listen_sock->state != NET_SOCK_STATE_ESTABLISHED) {
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
}
/* 单连接模式PASV查 standalone 监听者是否已 ESTABLISHED */
if (p_listen_sock->standalone_accept &&
p_listen_sock->state == NET_SOCK_STATE_ESTABLISHED) {
if (NULL != addr &&NULL != addrlen) {
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;
/* 填充对端地址(若调用方需要) */
if (NULL != addr && NULL != addrlen) {
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);
}
s_net_errno = NET_ERR_WOULDBLOCK;
return -1;
/* 单连接:返回的就是监听 Socket 自身(已转为数据通道) */
return sockfd;
}
/*
@@ -897,9 +838,6 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags) {
return -1;
}
if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
return 0;
}
if (p_sock->state == NET_SOCK_STATE_CLOSED) {
/* 断开前尝试排空 CH395F 接收缓冲区Trap 13FIN 可能比数据先到) */
uint16_t rem = ch395f_get_recv_len(sockfd);
@@ -1485,44 +1423,14 @@ static int alloc_socket(void) {
* 出口参数:无
* 返回值:无
* 限定条件net_poll() 检测到 CONNECT 中断后调用netTask 上下文
* 函数说明1. 独立监听模式standalone_accept:自身转 ESTABLISHED 并读取对端地址
* 2. 多连接监听模式Socket 0 保持 LISTENING由数据 Socket 承接连接
* 3. 连接模式自动打开的数据 Socket首次 CONNECT 时初始化并置 ESTABLISHED
* 4. TCP ClientCONNECTING连接成功读取对端地址并置 ESTABLISHED
* 5. 数据 SocketTCP_ACCEPT被分配连接置 ESTABLISHED
* 6. 连接成功后使能 KeepAlive 并触发 NET_EVENT_CONNECTED 回调
* 函数说明1. 单连接:自身转 ESTABLISHED 并读取对端地址
* 2. TCP ClientCONNECTING连接成功读取对端地址并置 ESTABLISHED
* 3. 连接成功后使能 KeepAlive 并触发 NET_EVENT_CONNECTED 回调
*/
static void handle_connect_event(net_sock_t *p_sock) {
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
if (p_sock->standalone_accept) {
/* 独立监听模式PASV收到 CONNECT 中断 = 自身有连接到达,转为 ESTABLISHED */
DBG_INFO("sock%d standalone accept", p_sock->ch395_sock);
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
p_sock->remote_ip = ((uint32_t)remote[0]) |
((uint32_t)remote[1] << 8) |
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
p_sock->send_ready = 1;
/* 清除残留的 TIMEOUT 中断标志 */
(void)ch395f_get_sock_int_status(p_sock->ch395_sock);
fire_event(p_sock, NET_EVENT_CONNECTED);
} else {
/* 多连接模式:监听 Socket 收到 CONNECT 中断 = 有新连接被分配到数据 Socket
* Socket 0 自身保持 LISTENING不需要改变状态 */
fire_event(p_sock, NET_EVENT_CONNECTED);
}
}
else if (!p_sock->in_use) {
/* CH395F 自动打开的数<E79A84>?Socket多连接模式首次收到 CONNECT 中断 */
int sock_idx = (int)(p_sock - s_net_socks);
p_sock->ch395_sock = (uint8_t)sock_idx;
DBG_INFO("sock%d AUTO-OPENED, CONNECTED", p_sock->ch395_sock);
/* 单连接:收到 CONNECT 中断 = 自身有连接到达,转为 ESTABLISHED */
DBG_INFO("sock%d standalone accept", p_sock->ch395_sock);
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
@@ -1531,15 +1439,14 @@ static void handle_connect_event(net_sock_t *p_sock) {
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->in_use = 1;
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
p_sock->send_ready = 1;
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
/* 清除残留的 TIMEOUT 中断标志 */
(void)ch395f_get_sock_int_status(p_sock->ch395_sock);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
else if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
} else if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
/* TCP Client 连接成功 */
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
@@ -1553,24 +1460,6 @@ static void handle_connect_event(net_sock_t *p_sock) {
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
else if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
/* 数据 Socket 被分配了连接 */
DBG_INFO("data sock%d TCP_ACCEPT -> CONNECTED", p_sock->ch395_sock);
uint8_t remote[6];
ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
memcpy(p_sock->remote_ip_arr, remote, 4);
p_sock->remote_ip = ((uint32_t)remote[0]) |
((uint32_t)remote[1] << 8) |
((uint32_t)remote[2] << 16) |
((uint32_t)remote[3] << 24);
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
p_sock->send_ready = 1;
ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);
fire_event(p_sock, NET_EVENT_CONNECTED);
}
}
@@ -1582,33 +1471,18 @@ static void handle_connect_event(net_sock_t *p_sock) {
* 返回值:无
* 限定条件net_poll() 检测到 DISCONNECT 中断后调用netTask 上下文
* 函数说明1. CH395F 在 DISCONNECT 后自动关闭 SocketFUN_PARA 默认),需重新 OPEN + LISTEN
* 2. 独立监听模式:置 CLOSED交由 net_recv_locked 排空剩余数据后再关
* 3. 多连接数据 Socket回到 TCP_ACCEPT 状态等待新连接
* 4. 触发 NET_EVENT_DISCONNECTED 回调
* 2. 单连接:置 CLOSED交由 net_recv_locked 排空剩余数据后再关
* 3. 触发 NET_EVENT_DISCONNECTED 回调
*/
static void handle_disconnect_event(net_sock_t *p_sock) {
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
DBG_ERROR("WARNING: listen sock%d got disconnect", p_sock->ch395_sock);
}
else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
if (p_sock->standalone_accept) {
/* 独立监听模式:先不关 CH395F Socket
* 留给 net_recv_locked 把剩余数据读出来再关 */
DBG_INFO("sock%d DISCONNECTED, releasing", p_sock->ch395_sock);
p_sock->state = NET_SOCK_STATE_CLOSED;
fire_event(p_sock, NET_EVENT_DISCONNECTED);
} else {
DBG_INFO("sock%d DISCONNECTED, back to idle", p_sock->ch395_sock);
memset(p_sock->remote_ip_arr, 0, 4);
p_sock->remote_port = 0;
p_sock->send_ready = 1;
p_sock->state = NET_SOCK_STATE_TCP_ACCEPT;
fire_event(p_sock, NET_EVENT_DISCONNECTED);
}
} else if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
memset(p_sock->remote_ip_arr, 0, 4);
p_sock->remote_port = 0;
p_sock->send_ready = 1;
} else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
/* 单连接:先不关 CH395F Socket
* 留给 net_recv_locked 把剩余数据读出来再关,置 CLOSED 等待应用重新监听 */
DBG_INFO("sock%d DISCONNECTED, releasing", p_sock->ch395_sock);
p_sock->state = NET_SOCK_STATE_CLOSED;
fire_event(p_sock, NET_EVENT_DISCONNECTED);
} else if (p_sock->state != NET_SOCK_STATE_CLOSED &&
p_sock->state != NET_SOCK_STATE_BOUND &&
p_sock->state != NET_SOCK_STATE_CREATED) {
@@ -1653,7 +1527,7 @@ static void handle_send_event(net_sock_t *p_sock) {
* 返回值:无
* 限定条件net_poll() 检测到 SOCK_TIMEOUT 中断后调用netTask 上下文
* 函数说明1. TCP ClientCONNECTING连接超时回到 CREATED 状态
* 2. 已建立连接:回到 CLOSED独立模式)或 TCP_ACCEPT多连接模式
* 2. 已建立连接:回到 CLOSED单连接
* 3. 监听态:异常超时,记录错误日志
* 4. 触发 NET_EVENT_TIMEOUT 回调
*/
@@ -1662,12 +1536,10 @@ static void handle_timeout_event(net_sock_t *p_sock) {
/* TCP Client 连接超时 */
DBG_ERROR("sock%d CONNECT TIMEOUT", p_sock->ch395_sock);
p_sock->state = NET_SOCK_STATE_CREATED;
}
else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
} else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
DBG_ERROR("sock%d TIMEOUT", p_sock->ch395_sock);
p_sock->state = p_sock->standalone_accept ? NET_SOCK_STATE_CLOSED : NET_SOCK_STATE_TCP_ACCEPT;
}
else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
p_sock->state = NET_SOCK_STATE_CLOSED;
} else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
/* 监听超时(异常情况) */
DBG_ERROR("sock%d LISTEN TIMEOUT", p_sock->ch395_sock);
}

View File

@@ -97,12 +97,11 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
/*
* 函数功能TCP Server 监听
* 入口参数sockfd - socket 描述符
* backlog - 最大等待连接数(多连接模式下为数据 Socket 数量)
* 返回值0 成功,-1 失败
* 限定条件socket 已绑定
* 函数说明:内部调用 ch395f_tcp_listen多连接模式自动配置数据 Socket
* 函数说明:内部调用 ch395f_tcp_listen监听 Socket 自身即为数据通道
*/
int net_listen(int sockfd, int backlog);
int net_listen(int sockfd);
/*
* 函数功能TCP Server 接受连接
@@ -333,11 +332,10 @@ 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);
int net_listen_locked(int sockfd);
#ifdef __cplusplus
}

View File

@@ -114,7 +114,6 @@ typedef enum {
NET_SOCK_STATE_CONNECTING, /* TCP Client 连接中 */
NET_SOCK_STATE_ESTABLISHED, /* TCP 已连接 */
NET_SOCK_STATE_UDP_OPEN, /* UDP 已打开 */
NET_SOCK_STATE_TCP_ACCEPT, /* TCP Server 数据 Socket等待分配连接 */
NET_SOCK_STATE_TCP_CLIENT_RECONNECTING, /* TCP Client 重连中 */
} net_sock_state_t;
@@ -156,16 +155,9 @@ typedef struct {
net_event_cb_t event_cb;
void *event_arg;
/* TCP Server 多连接模式:监听 Socket 的数据 Socket 列表 */
int data_socks[NET_TCP_SERVER_MAX_CLIENTS];
int data_sock_count;
/* 发送就绪标志 */
uint8_t send_ready;
/* 独立监听标志PASV 用):该 Socket 为独立监听者,收到 CONNECT 后转为 ESTABLISHED断开后释放 */
uint8_t standalone_accept;
/* 统计信息 */
uint32_t recv_bytes; /* 累计接收字节数 */
uint32_t send_bytes; /* 累计发送字节数 */