增加文件系统
This commit is contained in:
@@ -98,6 +98,13 @@ extern "C" {
|
||||
#define NET_POLL_DELAY_MS 1 /* 非阻塞轮询延时 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 消息队列配置
|
||||
*/
|
||||
#ifndef NET_MSG_QUEUE_LENGTH
|
||||
#define NET_MSG_QUEUE_LENGTH 8 /* 消息队列深度 */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,24 +1,50 @@
|
||||
/*
|
||||
* 模块名称:Network Select Implementation
|
||||
* 模块功能:I/O 多路复用实现,包<EFBFBD>?select <EFBFBD>?poll 模式<EFBFBD>? * 用于同时监控多个 Socket 的读写事<EFBFBD>? * 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建<EFBFBD>? * 创建日期<E697A5>?026-07-18
|
||||
* 修改记录<EFBFBD>? */
|
||||
* 模块功能:I/O 多路复用实现,包括 select 和 poll 两种模式,用于同时监控多个 Socket 的读写事件
|
||||
* 适用平台:STM32F407ZGTx + CH395F 以太网芯片
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
* 2026-07-18 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cmsis_os.h" /* CMSIS-RTOS2 API: osDelay() */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "net_select.h"
|
||||
#include "net_socket.h"
|
||||
#include "ch395f.h"
|
||||
#include "main.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 模式<EFBFBD>? */
|
||||
* 函数功能:I/O 多路复用(select 模式),等待多个 Socket 的读写事件就绪
|
||||
* 入口参数:nfds - 最大文件描述符数 +1 int > 0
|
||||
* readfds - 读事件集合指针 net_fd_set *(可为 NULL)
|
||||
* writefds - 写事件集合指针 net_fd_set *(可为 NULL)
|
||||
* exceptfds- 异常事件集合指针 net_fd_set *(可为 NULL)
|
||||
* timeout - 超时时间结构体指针 net_timeval *(NULL=无限等待)
|
||||
* 返回值:就绪的 Socket 数量 int >= 0 || -1
|
||||
* -1 - 参数无效 int
|
||||
* 限定条件:net_init() + MX_FREERTOS_Init() 已执行;必须在 netTask 上下文中调用
|
||||
* 函数说明:轮询所有 Socket,检查读/写/异常事件是否就绪。阻塞等待直到有事件或超时
|
||||
*/
|
||||
|
||||
int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
net_fd_set *exceptfds, net_timeval *timeout) {
|
||||
uint32_t start_tick;
|
||||
@@ -89,8 +115,8 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
}
|
||||
}
|
||||
|
||||
/* 短暂延时避免忙等 */
|
||||
HAL_Delay(NET_POLL_DELAY_MS);
|
||||
/* 让出 CPU:FreeRTOS osDelay() 会正确进入休眠,允许其他任务运行 */
|
||||
osDelay(1); /* 1ms 周期轮询,平衡实时性和 CPU 利用率 */
|
||||
}
|
||||
|
||||
/* 复制结果 */
|
||||
@@ -108,7 +134,15 @@ int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(poll 模式<EFBFBD>? */
|
||||
* 函数功能:I/O 多路复用(poll 模式),等待多个 Socket 的读写事件就绪
|
||||
* 入口参数:fds - pollfd 数组指针 net_pollfd *
|
||||
* nfds - 数组元素数量 int > 0
|
||||
* timeout - 超时时间(毫秒) int >= 0
|
||||
* 返回值:就绪的 fd 数量 int >= 0 || -1
|
||||
* -1 - 参数无效 int
|
||||
* 限定条件:net_init() + MX_FREERTOS_Init() 已执行;必须在 netTask 上下文中调用
|
||||
* 函数说明:轮询所有 Socket,检查读/写/错误/挂起事件是否就绪。阻塞等待直到有事件或超时
|
||||
*/
|
||||
int net_poll_events(net_pollfd *fds, int nfds, int timeout) {
|
||||
uint32_t start_tick;
|
||||
int ready = 0;
|
||||
@@ -185,7 +219,8 @@ int net_poll_events(net_pollfd *fds, int nfds, int timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Delay(NET_POLL_DELAY_MS);
|
||||
/* 让出 CPU:FreeRTOS osDelay() 会正确进入休眠,允许其他任务运行 */
|
||||
osDelay(1); /* 1ms 周期轮询,平衡实时性和 CPU 利用率 */
|
||||
}
|
||||
|
||||
return ready;
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
/*
|
||||
* 模块名称:Network Socket Core
|
||||
* 模块功能:BSD Socket API 核心实现,包<EFBFBD>?Socket 管理、状态机<EFBFBD>? * 事件处理、数据收发等功能,底层调<EFBFBD>?CH395F 驱动
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建<EFBFBD>? * 创建日期<E697A5>?026-07-18
|
||||
* 修改记录<EFBFBD>? */
|
||||
* 模块功能:BSD Socket API 核心实现,包含 Socket 管理、状态机、消息队列(线程安全)、事件处理、数据收发等功能,底层调用 CH395F 驱动
|
||||
* 适用平台:STM32F407ZGTx + CH395F 以太网芯片
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
* 2026-07-18 王建锋 创建初始版本
|
||||
* 2026-07-19 王建锋 添加消息队列线程安全机制,替换 xQueueCreate 为 CubeMX osMessageQueue
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#include "net_socket.h"
|
||||
#include "ch395f.h"
|
||||
#include "main.h"
|
||||
@@ -20,21 +29,32 @@
|
||||
/*
|
||||
* 私有宏定义区
|
||||
*/
|
||||
#define NET_PHY_CHECK_INTERVAL_MS 5000U /* PHY 状态定期检查间隔(ms) */
|
||||
|
||||
/*
|
||||
* 私有变量<EFBFBD>? */
|
||||
static net_sock_t s_net_socks[NET_MAX_SOCKETS]; /* Socket 控制块数<E59D97>?*/
|
||||
static int s_net_errno = 0; /* 最后错误码 */
|
||||
static uint8_t s_net_initialized = 0; /* 初始化标<E58C96>?*/
|
||||
|
||||
|
||||
/*
|
||||
* 私有宏定义区 - 补充
|
||||
* 全局变量定义区 - 尽量避免使用全局变量
|
||||
*/
|
||||
#define NET_PHY_CHECK_INTERVAL_MS 5000U /* PHY 状态定期检查间隔(ms<6D>?*/
|
||||
static net_sock_t s_net_socks[NET_MAX_SOCKETS]; /* Socket 控制块数组 */
|
||||
static int s_net_errno = 0; /* 最后错误码 */
|
||||
static uint8_t s_net_initialized = 0; /* 初始化标志 */
|
||||
|
||||
/*
|
||||
* 私有函数声明<EFBFBD>? */
|
||||
* 消息队列 - 线程安全核心
|
||||
* 外部任务通过 net_send/net_recv/net_close 等 API 将请求放入队列,
|
||||
* netTask 调用 net_process_messages() 串行处理所有 CH395F 操作
|
||||
* 由 CubeMX 在 MX_FREERTOS_Init()(osKernelInitialize 之后)中创建
|
||||
*/
|
||||
extern osMessageQueueId_t netMsgQueueHandle; /* CubeMX 生成的消息队列句柄 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 私有函数声明区
|
||||
*/
|
||||
|
||||
static int alloc_socket(void);
|
||||
static void handle_connect_event(net_sock_t *p_sock);
|
||||
static void handle_disconnect_event(net_sock_t *p_sock);
|
||||
@@ -43,31 +63,50 @@ static void handle_send_event(net_sock_t *p_sock);
|
||||
static void handle_timeout_event(net_sock_t *p_sock);
|
||||
static void fire_event(net_sock_t *p_sock, net_event_t event);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 公共函数实现<EFBFBD>? */
|
||||
|
||||
/*
|
||||
* 函数功能:网络子系统初始<EFBFBD>? */
|
||||
* 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式)
|
||||
* 入口参数:ip - IP 地址字符串 "192.168.1.100",NULL 使用 DHCP 自动获取 const char *
|
||||
* mask - 子网掩码字符串 "255.255.255.0",NULL 使用默认值 const char *
|
||||
* gateway - 网关地址字符串 "192.168.1.1",NULL 使用默认值 const char *
|
||||
* 返回值:0 - 初始化成功 int
|
||||
* -1 - 初始化失败(芯片检测/复位/协议栈初始化失败) int
|
||||
* 限定条件:SPI2 已正确初始化;netTask 尚未启动
|
||||
* 函数说明:1. 检查 CH395F 芯片是否存在并复位
|
||||
* 2. 启用 TCP Server 多连接模式(bit1=1),设置 TCP MSS、重传参数、KeepAlive 参数
|
||||
* 3. 配置 IP/网关/子网掩码,或启用 DHCP
|
||||
* 4. 初始化 CH395F 协议栈并使能 PING 响应
|
||||
*/
|
||||
int net_init(const char *ip, const char *mask, const char *gateway) {
|
||||
ch395f_status_t ret;
|
||||
|
||||
/* 清零 Socket 控制<E68EA7>?*/
|
||||
DBG_INFO("net_init: start");
|
||||
|
||||
/* 清零 Socket 控制块 */
|
||||
memset(s_net_socks, 0, sizeof(s_net_socks));
|
||||
s_net_errno = 0;
|
||||
s_net_initialized = 0;
|
||||
|
||||
/* 检<>?CH395F 芯片 */
|
||||
DBG_INFO("net_init: queue=%p", (void *)netMsgQueueHandle);
|
||||
|
||||
DBG_INFO("net_init: check_exist...");
|
||||
/* 检查 CH395F 芯片 */
|
||||
if (ch395f_check_exist() != CH395F_STATUS_OK) {
|
||||
DBG_ERROR("net_init: ch395f_check_exist FAILED");
|
||||
s_net_errno = NET_ERR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_INFO("net_init: reset...");
|
||||
/* 复位芯片 */
|
||||
ch395f_reset();
|
||||
DBG_INFO("net_init: set_fun_para...");
|
||||
|
||||
/* 启用 TCP Server 多连接模式(bit1=1<EFBFBD>? * Socket 0 专职监听,Socket 1~7 自动分配给新连接 */
|
||||
/* 启用 TCP Server 多连接模式(bit1=1) */
|
||||
ch395f_set_fun_para(0x02);
|
||||
DBG_INFO("net_init: set_tcp_mss...");
|
||||
|
||||
/* 设置 TCP MSS */
|
||||
ch395f_set_tcp_mss(1460);
|
||||
@@ -115,7 +154,14 @@ int net_init(const char *ip, const char *mask, const char *gateway) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:轮询所<EFBFBD>?Socket 状<>? */
|
||||
* 函数功能:轮询 CH395F 中断状态,更新 Socket 连接状态并处理事件
|
||||
* 返回值:本次轮询中发生事件的 Socket 数量 int >= 0
|
||||
* 限定条件:s_net_initialized == 1;必须在 netTask 上下文中调用
|
||||
* 函数说明:1. GPIO 轮询 CH395F INT# 引脚电平(低电平有效),无需 EXTI 中断
|
||||
* 2. 读取 GET_GLOB_INT_STATUS_ALL(2 字节版)获取所有 Socket 的中断状态
|
||||
* 3. 处理连接/断开/数据接收/发送完成/超时等事件,更新 Socket 状态机
|
||||
* 4. RECV 中断为电平触发,每次 net_poll() 只处理一批中断,避免主循环饿死
|
||||
*/
|
||||
int net_poll(void) {
|
||||
int event_count = 0;
|
||||
int i;
|
||||
@@ -126,7 +172,9 @@ int net_poll(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO 轮询模式:仅<EFBFBD>?INT# 有效(低电平)时读取中断状<EFBFBD>? * 读取 GET_GLOB_INT_STATUS_ALL <20>?CH395F 拉高 INT#,若仍有中断则再次拉<E6ACA1>? */
|
||||
* GPIO 轮询模式:仅当 INT# 有效(低电平)时读取中断状态。
|
||||
* 读取 GET_GLOB_INT_STATUS_ALL,CH395F 拉高 INT#;若仍有中断则再次拉低。
|
||||
*/
|
||||
do
|
||||
{
|
||||
if (HAL_GPIO_ReadPin(CH395_INT_GPIO_Port, CH395_INT_Pin) == GPIO_PIN_SET) {
|
||||
@@ -139,7 +187,8 @@ int net_poll(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 诊断:每 3 秒打印一次全局中断状态和 Socket 状<EFBFBD>? * 注意:使用已读取的 int_status,不要再读 GINT(读即清除<E6B885>?*/
|
||||
/* 诊断:每 3 秒打印一次全局中断状态和 Socket 状态。
|
||||
* 注意:使用已读取的 int_status,不要再读 GINT(读即清除)。 */
|
||||
static uint32_t s_last_diag = 0;
|
||||
uint32_t now_diag = HAL_GetTick();
|
||||
if ((now_diag - s_last_diag >= 3000) || s_last_diag == 0) {
|
||||
@@ -208,11 +257,13 @@ int net_poll(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 处理完毕后检<EFBFBD>?INT# 是否仍为低电<EFBFBD>? * 如果是,说明在处理期间有新中断产生,需要再次读<EFBFBD>? *
|
||||
* 注意:CH395F <EFBFBD>?RECV 中断是电平触发的(只要接收缓冲区有数据就保持低电平)<EFBFBD>? * 如果不跳出循环,net_poll() 会无限循环处<E78EAF>?RECV 中断<E4B8AD>? * 导致主循环中的应用代码(<E7A081>?echo)永远无法执行<E689A7>? * 因此每次 net_poll() 调用只处理一批中断,由主循环负责读取数据<E695B0>? */
|
||||
* 处理完毕后检查 INT# 是否仍为低电平。如果是,说明在处理期间有新中断产生,需要再次读取。
|
||||
* 注意:CH395F 的 RECV 中断是电平触发的(只要接收缓冲区有数据就保持低电平)。
|
||||
* 如果不跳出循环,net_poll() 会无限循环处理 RECV 中断,导致主循环中的应用代码(如 echo)永远无法执行。
|
||||
* 因此每次 net_poll() 调用只处理一批中断,由主循环负责读取数据。 */
|
||||
} while (0);
|
||||
|
||||
/* <EFBFBD>?2 秒打印一次诊断信息(调试用) */
|
||||
/* 2 秒打印一次诊断信息(调试用) */
|
||||
{
|
||||
static uint32_t s_last_dbg = 0;
|
||||
uint32_t now = HAL_GetTick();
|
||||
@@ -235,13 +286,76 @@ int net_poll(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:创<EFBFBD>?socket
|
||||
* 函数功能:处理消息队列中的请求
|
||||
* 限定条件:必须在 netTask 上下文中调用(独占 CH395F 和 s_net_socks 访问权)
|
||||
* 函数说明:每次调用处理一条消息。处理 send/recv 时内部会调用 net_poll()
|
||||
* 等待操作完成。处理完毕后通知调用方任务。
|
||||
*/
|
||||
void net_process_messages(void) {
|
||||
net_msg_t msg;
|
||||
|
||||
if (netMsgQueueHandle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (osMessageQueueGet(netMsgQueueHandle, &msg, NULL, 0) == osOK) {
|
||||
switch (msg.type) {
|
||||
case NET_MSG_SEND: {
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL || p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
msg.result = -1;
|
||||
} else {
|
||||
msg.result = net_send_locked(p_sock, msg.buf, msg.len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NET_MSG_RECV: {
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
msg.result = -1;
|
||||
} else {
|
||||
msg.result = net_recv_locked(p_sock, msg.buf, msg.len, msg.flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NET_MSG_CLOSE: {
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
msg.result = -1;
|
||||
} else {
|
||||
msg.result = net_close_locked(p_sock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NET_MSG_CONNECT: {
|
||||
msg.result = net_connect(msg.sockfd,
|
||||
(const struct net_sockaddr *)&msg.addr,
|
||||
msg.addrlen);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
msg.result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
xTaskNotifyGive(msg.caller);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:创建 Socket,分配空闲 Socket 控制块并初始化状态
|
||||
* 入口参数:domain - 地址族,仅支持 NET_AF_INET int
|
||||
* type - SOCK_STREAM(TCP) 或 SOCK_DGRAM(UDP) int
|
||||
* protocol - 通常为 0 int
|
||||
* 返回值:Socket 描述符 (0~7),失败返回 -1 int
|
||||
* 限定条件:net_init() 已调用成功;s_net_initialized == 1
|
||||
* 函数说明:自动分配一个空闲的 Socket 控制块(in_use=0),初始化为 CREATED 状态
|
||||
*/
|
||||
int net_socket(int domain, int type, int protocol) {
|
||||
int sockfd;
|
||||
net_sock_t *p_sock;
|
||||
|
||||
/* 参数检<EFBFBD>?*/
|
||||
/* 参数检查*/
|
||||
if (domain != NET_AF_INET) {
|
||||
s_net_errno = NET_ERR_INVAL;
|
||||
return -1;
|
||||
@@ -265,7 +379,17 @@ int net_socket(int domain, int type, int protocol) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:绑定本地地址和端<EFBFBD>? */
|
||||
* 函数功能:绑定 Socket 到本地 IP 地址和端口号
|
||||
* 入口参数:sockfd - Socket 描述符 (0~7) int
|
||||
* addr - 本地地址结构体指针 const struct net_sockaddr *
|
||||
* addrlen - 地址结构体长度 int >= sizeof(struct net_sockaddr_in)
|
||||
* 返回值:0 - 绑定成功 int
|
||||
* -1 - 绑定失败(参数无效、Socket 未使用等) int
|
||||
* 限定条件:Socket 已通过 net_socket() 创建且未被其他操作占用;net_init() 已调用
|
||||
* 函数说明:1. TCP Socket 仅记录本地端口,进入 BOUND 状态等待 listen
|
||||
* 2. UDP Socket(SOCK_DGRAM)立即打开 CH395F Socket 并配置为 Server 模式
|
||||
* - Socket 4~7 需显式分配收发缓冲区
|
||||
*/
|
||||
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
|
||||
net_sock_t *p_sock;
|
||||
const struct net_sockaddr_in *p_addr_in;
|
||||
@@ -327,7 +451,15 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:TCP Server 监听
|
||||
* 函数功能:启动 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
|
||||
*/
|
||||
int net_listen(int sockfd, int backlog) {
|
||||
net_sock_t *p_sock;
|
||||
@@ -351,8 +483,10 @@ int net_listen(int sockfd, int backlog) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 多连接模式:先为数据 Socket 设置协议类型、源端口和独立缓冲区<EFBFBD>? * 必须在监听话<E590AC>?Socket OPEN+LISTEN 之前配置,确<EFBC8C>?CH395F <20>? * 自动分配机制能扫描到所有可<E69C89>?Socket
|
||||
* CH395F 根据源端口匹配、协议类<E8AEAE>?TCP、状<E38081>?CLOSED 查找可用 Socket */
|
||||
/* 多连接模式:先为数据 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);
|
||||
@@ -393,7 +527,13 @@ int net_listen(int sockfd, int backlog) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:TCP Server 接受连接
|
||||
* 函数功能: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
|
||||
*/
|
||||
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
|
||||
net_sock_t *p_listen_sock;
|
||||
@@ -438,7 +578,15 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:TCP Client 发起连接
|
||||
* 函数功能:TCP Client 发起与服务器的连接
|
||||
* 入口参数:sockfd - Socket 描述符 (0~7),必须为已创建的 TCP Socket int
|
||||
* addr - 服务器地址结构体指针 const struct net_sockaddr *
|
||||
* addrlen - 地址结构体长度 int >= sizeof(struct net_sockaddr_in)
|
||||
* 返回值:0 - 连接请求发送成功(异步,需等待 ESTABLISHED) int
|
||||
* -1 - 连接失败(参数无效、状态错误等) int
|
||||
* 限定条件:Socket 已通过 net_socket() 创建且 type == NET_SOCK_STREAM;尚未连接
|
||||
* 函数说明:设置目标 IP 和端口后打开 CH395F Socket,进入 CONNECTING 状态。连接建立需等待
|
||||
* net_poll() 检测到 CONNECT 事件并将状态更新为 ESTABLISHED
|
||||
*/
|
||||
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
|
||||
net_sock_t *p_sock;
|
||||
@@ -494,47 +642,37 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:发送数据(TCP<EFBFBD>? */
|
||||
int net_send(int sockfd, const void *buf, int len, int flags) {
|
||||
net_sock_t *p_sock;
|
||||
* 函数功能:发送数据(内部锁定版本,必须在 netTask 上下文调用)
|
||||
*/
|
||||
static int net_send_locked(net_sock_t *p_sock, const void *buf, int len) {
|
||||
int sent = 0;
|
||||
uint32_t tick_start;
|
||||
|
||||
/* 参数检<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->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
s_net_errno = NET_ERR_NOTCONN;
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)(p_sock - s_net_socks);
|
||||
|
||||
if (buf == NULL || len <= 0) {
|
||||
s_net_errno = NET_ERR_INVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
s_net_errno = NET_ERR_NOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tick_start = HAL_GetTick();
|
||||
|
||||
/* 分块发<E59D97>?*/
|
||||
while (sent < len) {
|
||||
int chunk = len - sent;
|
||||
if (chunk > NET_SEND_BUF_SIZE) {
|
||||
chunk = NET_SEND_BUF_SIZE;
|
||||
}
|
||||
|
||||
/* 检查发送缓冲区是否空闲 */
|
||||
if (!p_sock->send_ready) {
|
||||
/* 超时检<E697B6>?*/
|
||||
if (NET_SEND_TIMEOUT_MS > 0 &&
|
||||
(HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
|
||||
s_net_errno = NET_ERR_TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
/* 继续轮询 */
|
||||
net_poll();
|
||||
continue;
|
||||
}
|
||||
@@ -544,7 +682,6 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
|
||||
sent += chunk;
|
||||
p_sock->send_bytes += (uint32_t)chunk;
|
||||
|
||||
/* 短暂延时等待发送完<E98081>?*/
|
||||
tick_start = HAL_GetTick();
|
||||
while (!p_sock->send_ready) {
|
||||
net_poll();
|
||||
@@ -559,30 +696,12 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(TCP<EFBFBD>? */
|
||||
int net_recv(int sockfd, void *buf, int len, int flags) {
|
||||
net_sock_t *p_sock;
|
||||
* 函数功能:接收数据(内部锁定版本,必须在 netTask 上下文调用)
|
||||
*/
|
||||
static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags) {
|
||||
uint16_t recv_len;
|
||||
uint32_t tick_start;
|
||||
|
||||
/* 参数检<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) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 检查连接状<E68EA5>?*/
|
||||
if (p_sock->type == NET_SOCK_STREAM &&
|
||||
p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
s_net_errno = NET_ERR_NOTCONN;
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)(p_sock - s_net_socks);
|
||||
|
||||
if (buf == NULL || len <= 0) {
|
||||
s_net_errno = NET_ERR_INVAL;
|
||||
@@ -596,35 +715,183 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
|
||||
|
||||
recv_len = ch395f_get_recv_len(sockfd);
|
||||
if (recv_len > 0) {
|
||||
/* 有数据可<E68DAE>?*/
|
||||
int read_len = (recv_len > (uint16_t)len) ? len : (int)recv_len;
|
||||
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
|
||||
p_sock->recv_bytes += (uint32_t)read_len;
|
||||
return read_len;
|
||||
}
|
||||
|
||||
/* 非阻塞模式检<E5BC8F>?*/
|
||||
if (flags & NET_MSG_DONTWAIT) {
|
||||
s_net_errno = NET_ERR_WOULDBLOCK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 超时检<E697B6>?*/
|
||||
if (NET_RECV_TIMEOUT_MS > 0 &&
|
||||
(HAL_GetTick() - tick_start) >= NET_RECV_TIMEOUT_MS) {
|
||||
s_net_errno = NET_ERR_TIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 连接已断开检<E5BC80>?*/
|
||||
if (p_sock->state == NET_SOCK_STATE_TCP_ACCEPT) {
|
||||
return 0; /* 对端关闭 */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:发<EFBFBD>?UDP 数据
|
||||
* 函数功能:关闭 socket(内部锁定版本,必须在 netTask 上下文调用)
|
||||
*/
|
||||
static int net_close_locked(net_sock_t *p_sock) {
|
||||
int sockfd = (int)(p_sock - s_net_socks);
|
||||
|
||||
ch395f_close_socket(sockfd);
|
||||
memset(p_sock, 0, sizeof(net_sock_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:发送数据(线程安全版本,通过消息队列委托给 netTask)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 待发送数据缓冲区指针 const void *
|
||||
* len - 数据长度 int > 0
|
||||
* flags - 标志位,通常为 0 int
|
||||
* 返回值:实际发送字节数 int >= 0 || -1
|
||||
* -1 - 发送失败(参数无效、队列满等) int
|
||||
* 限定条件:Socket 处于 ESTABLISHED 状态;net_init() + MX_FREERTOS_Init() 已执行;非 netTask 上下文
|
||||
* 函数说明:将发送请求放入消息队列,阻塞等待 netTask 处理完毕并返回结果。netTask 内请使用 net_send_sock()
|
||||
*/
|
||||
int net_send(int sockfd, const void *buf, int len, int flags) {
|
||||
(void)flags;
|
||||
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_SEND;
|
||||
msg.sockfd = sockfd;
|
||||
msg.buf = (void *)buf;
|
||||
msg.len = len;
|
||||
msg.flags = 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 (msg.result < 0) {
|
||||
s_net_errno = NET_ERR;
|
||||
}
|
||||
return msg.result;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(线程安全版本,通过消息队列委托给 netTask)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 接收缓冲区指针 void *
|
||||
* len - 缓冲区大小 int > 0
|
||||
* flags - 标志位,0=阻塞,NET_MSG_DONTWAIT=非阻塞 int
|
||||
* 返回值:实际接收字节数 int >= 0 || 0 || -1
|
||||
* 0 - 对端关闭连接 int
|
||||
* -1 - 接收失败(参数无效、队列满等) int
|
||||
* 限定条件:Socket 处于 ESTABLISHED 状态;net_init() + MX_FREERTOS_Init() 已执行;非 netTask 上下文
|
||||
* 函数说明:将接收请求放入消息队列,阻塞等待 netTask 处理完毕并返回结果。netTask 内请使用 net_recv_sock()
|
||||
*/
|
||||
int net_recv(int sockfd, void *buf, int len, int flags) {
|
||||
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_RECV;
|
||||
msg.sockfd = sockfd;
|
||||
msg.buf = buf;
|
||||
msg.len = len;
|
||||
msg.flags = flags;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:关闭 Socket(线程安全版本,通过消息队列委托给 netTask)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* 返回值:0 - 关闭成功 int
|
||||
* -1 - 关闭失败 int
|
||||
* 限定条件:Socket 已创建且处于非 CLOSED 状态;net_init() + MX_FREERTOS_Init() 已执行;非 netTask 上下文
|
||||
* 函数说明:将关闭请求放入消息队列,阻塞等待 netTask 处理完毕。TCP Socket 先断开连接再释放控制块。
|
||||
* netTask 内请使用 net_close_sock()
|
||||
*/
|
||||
int net_close(int sockfd) {
|
||||
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_CLOSE;
|
||||
msg.sockfd = sockfd;
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 函数功能:发送 UDP 数据报(含目标地址)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 待发送数据缓冲区指针 const void *
|
||||
* len - 数据长度 int > 0
|
||||
* flags - 标志位,通常为 0 int
|
||||
* dest_addr - 目标地址结构体指针 const struct net_sockaddr *
|
||||
* addrlen - 目标地址结构体长度 int >= sizeof(struct net_sockaddr_in)
|
||||
* 返回值:实际发送字节数 int > 0 || -1
|
||||
* -1 - 发送失败 int
|
||||
* 限定条件:Socket 已创建且为 UDP 类型(SOCK_DGRAM);net_init() 已调用
|
||||
*/
|
||||
int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
const struct net_sockaddr *dest_addr, int addrlen) {
|
||||
@@ -704,9 +971,17 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:接<EFBFBD>?UDP 数据
|
||||
* 函数功能:接收 UDP 数据报(含源地址)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 接收缓冲区指针 void *
|
||||
* len - 缓冲区大小 int > 0
|
||||
* flags - 标志位,通常为 0 int
|
||||
* src_addr - 输出:发送方地址结构体指针 struct net_sockaddr *(可为 NULL)
|
||||
* addrlen - 输入输出:源地址长度 int *(可为 NULL)
|
||||
* 返回值:实际接收字节数 int >= 0 || -1
|
||||
* -1 - 接收失败 int
|
||||
* 限定条件:Socket 已创建且为 UDP 类型(SOCK_DGRAM);net_init() 已调用;有数据可用
|
||||
*/
|
||||
int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
struct net_sockaddr *src_addr, int *addrlen) {
|
||||
@@ -784,34 +1059,59 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:关<EFBFBD>?socket
|
||||
* 函数功能:发送数据(内部版本,绕过消息队列,供 netTask 直接使用)
|
||||
*/
|
||||
int net_close(int sockfd) {
|
||||
net_sock_t *p_sock;
|
||||
|
||||
/* 参数检<E695B0>?*/
|
||||
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
|
||||
int net_send_sock(net_sock_t *p_sock, const void *buf, int len) {
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_sock = &s_net_socks[sockfd];
|
||||
if (!p_sock->in_use) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 关闭 CH395F Socket */
|
||||
ch395f_close_socket(sockfd);
|
||||
|
||||
/* 清零控制<E68EA7>?*/
|
||||
memset(p_sock, 0, sizeof(net_sock_t));
|
||||
|
||||
return 0;
|
||||
return net_send_locked(p_sock, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:注册事件回<EFBFBD>? */
|
||||
* 函数功能:接收数据(内部版本,绕过消息队列,供 netTask 直接使用)
|
||||
* 入口参数:p_sock - Socket 控制块指针 net_sock_t *
|
||||
* buf - 接收缓冲区指针 void *
|
||||
* len - 缓冲区大小 int > 0
|
||||
* flags - 标志位,NET_MSG_DONTWAIT=非阻塞 int
|
||||
* 返回值:实际接收字节数 int >= 0 || 0 || -1
|
||||
* 0 - 对端关闭连接 int
|
||||
* -1 - 接收失败 int
|
||||
* 限定条件:必须在 netTask 上下文中调用;p_sock->in_use == 1
|
||||
* 函数说明:直接操作 Socket 控制块,不经过消息队列。避免 netTask 向自身发送消息造成死锁
|
||||
*/
|
||||
int net_recv_sock(net_sock_t *p_sock, void *buf, int len, int flags) {
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
return -1;
|
||||
}
|
||||
return net_recv_locked(p_sock, buf, len, flags);
|
||||
}
|
||||
/*
|
||||
* 函数功能:关闭 Socket(内部版本,绕过消息队列,供 netTask 直接使用)
|
||||
* 入口参数:p_sock - Socket 控制块指针 net_sock_t *
|
||||
* 返回值:0 - 关闭成功 int
|
||||
* -1 - 关闭失败 int
|
||||
* 限定条件:必须在 netTask 上下文中调用;p_sock->in_use == 1
|
||||
* 函数说明:直接操作 Socket 控制块,不经过消息队列。TCP Socket 先断开连接再释放控制块
|
||||
*/
|
||||
int net_close_sock(net_sock_t *p_sock) {
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
return -1;
|
||||
}
|
||||
return net_close_locked(p_sock);
|
||||
}
|
||||
/*
|
||||
* 函数功能:注册 Socket 事件回调函数
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* cb - 回调函数指针 net_event_cb_t(可为 NULL 取消注册)
|
||||
* arg - 用户自定义参数指针 void *
|
||||
* 返回值:0 - 注册成功 int
|
||||
* -1 - 注册失败 int
|
||||
* 限定条件:Socket 已创建且 in_use == 1;net_init() 已调用
|
||||
*/
|
||||
|
||||
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
|
||||
net_sock_t *p_sock;
|
||||
|
||||
@@ -832,10 +1132,13 @@ int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获<EFBFBD>?socket 最后错误码
|
||||
* 函数功能:获取 Socket 最后一次操作返回的错误码
|
||||
* 返回值:当前错误码值(NET_OK=0, NET_ERR_xxx=-N) int
|
||||
* 限定条件:无
|
||||
* 函数说明:每次 net_*() API 调用失败后,错误码被设置。调用成功时不自动清零
|
||||
*/
|
||||
|
||||
int net_get_errno(void) {
|
||||
return s_net_errno;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,31 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "net_types.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*
|
||||
* 消息队列类型定义
|
||||
*/
|
||||
typedef enum {
|
||||
NET_MSG_SEND,
|
||||
NET_MSG_RECV,
|
||||
NET_MSG_CLOSE,
|
||||
NET_MSG_CONNECT,
|
||||
} net_msg_type_t;
|
||||
|
||||
typedef struct {
|
||||
net_msg_type_t type; /* 操作类型 */
|
||||
int sockfd; /* Socket 描述符 */
|
||||
void *buf; /* 数据缓冲区(send/recv) */
|
||||
int len; /* 数据长度/缓冲区大小 */
|
||||
int flags; /* 接收标志 */
|
||||
TaskHandle_t caller; /* 调用方任务句柄 */
|
||||
int result; /* 操作结果 */
|
||||
/* 连接参数 */
|
||||
struct net_sockaddr_in addr; /* 连接地址 */
|
||||
int addrlen; /* 地址长度 */
|
||||
} net_msg_t;
|
||||
|
||||
/*
|
||||
* 网络初始化接口
|
||||
@@ -245,6 +270,14 @@ uint32_t net_htonl(uint32_t hostlong);
|
||||
*/
|
||||
uint32_t net_ntohl(uint32_t netlong);
|
||||
|
||||
/*
|
||||
* 函数功能:处理消息队列中的请求(必须在 netTask 主循环中调用)
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:处理其他任务通过 net_send/net_recv 等接口发送的请求,
|
||||
* 在 netTask 上下文中串行化执行所有 CH395F 操作
|
||||
*/
|
||||
void net_process_messages(void);
|
||||
|
||||
/*
|
||||
* 函数功能:获取 Socket 控制块指针(内部使用)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
@@ -252,6 +285,39 @@ uint32_t net_ntohl(uint32_t netlong);
|
||||
*/
|
||||
net_sock_t *net_get_sock(int sockfd);
|
||||
|
||||
/*
|
||||
* 内部 API(需在 netTask 上下文中调用,绕过消息队列)
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:发送数据(内部版本,直接操作,不经过消息队列)
|
||||
* 入口参数:p_sock - Socket 控制块指针
|
||||
* buf - 数据缓冲区
|
||||
* len - 数据长度
|
||||
* 返回值:实际发送字节数,失败返回 -1
|
||||
* 限定条件:必须在 netTask 上下文中调用
|
||||
*/
|
||||
int net_send_sock(net_sock_t *p_sock, const void *buf, int len);
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(内部版本,直接操作,不经过消息队列)
|
||||
* 入口参数:p_sock - Socket 控制块指针
|
||||
* buf - 接收缓冲区
|
||||
* len - 缓冲区大小
|
||||
* flags - 通常为 0,可设置 NET_MSG_DONTWAIT
|
||||
* 返回值:实际接收字节数,0=对端关闭,-1=错误
|
||||
* 限定条件:必须在 netTask 上下文中调用
|
||||
*/
|
||||
int net_recv_sock(net_sock_t *p_sock, void *buf, int len, int flags);
|
||||
|
||||
/*
|
||||
* 函数功能:关闭 socket(内部版本,直接操作,不经过消息队列)
|
||||
* 入口参数:p_sock - Socket 控制块指针
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:必须在 netTask 上下文中调用
|
||||
*/
|
||||
int net_close_sock(net_sock_t *p_sock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user