a8442410d1
B10 根治 P1(不变量 I):把"这条会话结束了"从 state==CLOSED 这一 **边沿**改成 session_dead **电平**,从结构上消掉两类事故。 问题:单连接复用模型下同一 fd 兼任监听器与连接(handle aliasing), "会话结束"原先只能在 state==CLOSED 那一刻被观察到。别的路径抢先 relisten 回 LISTENING(对账④ / net_accept_locked 的 CLOSED 分支) 后,消费者再 recv 恒得 WOULDBLOCK → EOF 永久失踪:慢消费者被饿死、 新客户端数据被旧会话静默吸收。 改动: - net_types.h:net_sock_t 增 session_dead(粘滞电平) - 置位 4 处:handle_disconnect_event 释放分支、handle_timeout_event ESTABLISHED 分支、net_connect_locked 命令被拒、对账①(复用前者) - 清零:handle_connect_event 两支;net_relisten_locked **刻意不清** (重建监听与"应用是否已确认会话结束"必须解耦,已注释钉住契约) - net_recv_locked DONTWAIT 判据改 CLOSED || session_dead - net_pending_tick ③ 断连判据同步改(**超出原清单的必要扩展**:不改 则 lftpd 阻塞 recv 在抢先 relisten 后两头落空、只能干等超时) - 两处 relisten 调用补内层 state==CLOSED 门:net_relisten_try 无 状态门,对已 LISTENING 的 fd 再 open+listen 会因 USE 错误走进关闭 分支、关掉正听着新 SYN 的 Socket(U12 同源事故) - ui_net_sink::563 真错误分支加 g_client != g_listen 护栏;EOF/ 错误后不再自行 bind_listen(消灭第 3/4 个重建所有者,不变量 II) - 新增 net_listener_armed()(LISTENING 或 CLOSED+auto_relisten)替代 accept 门控的 net_can_accept()——旧门控使 :7003 永不进 net_accept, net_lost_connect_probe(丢 CONNECT 补 accept,N-30)形同从未运行。 MCU 与 net_socket_sim.c 双端实现(sim 端恒 1,保持改前行为) 验证:@build 0 错 0 警(Code=197096,基线 197084,+12B); mem-numbers 快照已 --write 刷新;cppcheck / C 规范 / 主机侧单测 12 套 / 双端注册 / CubeMX 存活 / 任务表 全绿。 ⚠ 提交时 SKIP=doc-links:该钩子在从当前 v2-on-ui 切出的工作树上必报 2 处失效引用(RAM 方案文档 → ram_baseline.tsv / RAM预算台账.md), 属另一在途任务未提交的文件,主工作树磁盘上有故主线门禁呈绿。非本次 引入,不代为提交他人半成品;待其合入自动消解(见 并行任务工作树方案.md §10.2)。
495 lines
20 KiB
C
495 lines
20 KiB
C
/*
|
||
* 模块名称:Network Socket API
|
||
* 模块功能:BSD Socket API 兼容接口,提供 TCP/UDP 网络通信功能,
|
||
* 底层基于 CH395F 以太网协议栈芯片
|
||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-07-18
|
||
* 修改记录:
|
||
*/
|
||
|
||
#ifndef NET_SOCKET_H
|
||
#define NET_SOCKET_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include "net_types.h"
|
||
|
||
/*
|
||
* OS 相关接口(FreeRTOS 消息队列 / 任务句柄 / netTask 内部 API)仅在启用
|
||
* RTOS 的构建(MCU)编译;纯 PC 模拟器定义 NET_NO_OS 后只保留 BSD Socket 核心 API。
|
||
*/
|
||
#ifndef NET_NO_OS
|
||
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#endif /* NET_NO_OS */
|
||
|
||
#ifndef NET_NO_OS
|
||
/*
|
||
* 消息队列类型定义
|
||
*/
|
||
typedef enum {
|
||
NET_MSG_SEND,
|
||
NET_MSG_RECV,
|
||
NET_MSG_CLOSE,
|
||
NET_MSG_CONNECT,
|
||
NET_MSG_LISTEN,
|
||
NET_MSG_ACCEPT,
|
||
NET_MSG_RESYNC_LISTEN, /* 仅修 MCU 侧状态(ESTABLISHED→LISTENING),不发芯片命令 */
|
||
NET_MSG_RELISTEN, /* 无条件芯片侧重监听(open+listen,含 Trap 09 重试) */
|
||
} net_msg_type_t;
|
||
|
||
typedef struct {
|
||
net_msg_type_t type; /* 操作类型 */
|
||
int sockfd; /* Socket 描述符 */
|
||
void *buf; /* 数据缓冲区(send/recv) */
|
||
int len; /* 数据长度/缓冲区大小 */
|
||
int flags; /* 接收标志 */
|
||
uint32_t timeout_ms; /* 接收超时(入队方向;0 = 用默认 NET_RECV_TIMEOUT_MS) */
|
||
TaskHandle_t caller; /* 调用方任务句柄 */
|
||
int result; /* 操作结果 */
|
||
/* 连接参数 */
|
||
struct net_sockaddr_in addr; /* 连接地址 */
|
||
int addrlen; /* 地址长度 */
|
||
} net_msg_t;
|
||
#endif /* NET_NO_OS */
|
||
|
||
/*
|
||
* 网络初始化接口
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式)
|
||
* 入口参数:ip - 本地 IP 地址字符串 "192.168.1.100",NULL 使用 DHCP
|
||
* mask - 子网掩码字符串 "255.255.255.0",NULL 使用默认
|
||
* gateway - 网关地址字符串 "192.168.1.1",NULL 使用默认
|
||
* mac - MAC 地址(6 字节,低字节在前),NULL 或全零使用芯片内置
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:SPI2 已正确初始化
|
||
* 函数说明:必须在所有网络操作之前调用;mac 非空且非全零时在协议栈初始化
|
||
* (CMD_INIT_CH395)之前下发(手册 §9.2.1 步骤①:SET_MAC 写芯片 EEPROM,
|
||
* INIT_CH395 加载 MAC——顺序反了则本次上电不生效,回落芯片内置/上次值)
|
||
*/
|
||
int net_init(const char *ip, const char *mask, const char *gateway, const uint8_t *mac);
|
||
|
||
/*
|
||
* 函数功能:取网络代次号
|
||
* 入口参数:无
|
||
* 返回值:代次号(每次网络重建完成递增) uint32_t
|
||
* 限定条件:无
|
||
* 函数说明:TCP 服务(FTP / 对时 / 远程显示)据此感知"网络已重建"——代次变化
|
||
* 表示旧 Socket 已随芯片复位失效,服务应放弃旧监听并重建。
|
||
* 递增点在 net_stack_bring_up() 末尾(PHY/链路就绪后),避免服务在网络
|
||
* 尚未可用时抢先重建、也避免 uiTask 阻塞在消息队列上。
|
||
*/
|
||
uint32_t net_get_generation(void);
|
||
|
||
/*
|
||
* 函数功能:递增网络代次号(网络重建完成、对外可用时调用)
|
||
* 入口参数:无
|
||
* 返回值:无
|
||
* 限定条件:net_init() 成功且 PHY/链路就绪后调用(当前仅 net_stack_bring_up)
|
||
* 函数说明:见 net_get_generation()
|
||
*/
|
||
void net_generation_inc(void);
|
||
|
||
/*
|
||
* 函数功能:轮询所有 Socket 状态(必须在主循环中调用)
|
||
* 返回值:有事件发生的 socket 数量
|
||
* 限定条件:net_init() 已调用
|
||
* 函数说明:此函数处理所有 Socket 的中断事件,更新状态,
|
||
* 并触发事件回调。在非阻塞模式下必须定期调用。
|
||
*/
|
||
int net_poll(void);
|
||
|
||
/*
|
||
* 核心 Socket API
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:创建 socket
|
||
* 入口参数:domain - 地址族,仅支持 AF_INET
|
||
* type - SOCK_STREAM(TCP) 或 SOCK_DGRAM(UDP)
|
||
* 返回值:socket 描述符 (0~7),失败返回 -1
|
||
* 限定条件:net_init() 已调用
|
||
* 函数说明:自动分配空闲 Socket 控制块
|
||
*/
|
||
int net_socket(int domain, int type);
|
||
|
||
/*
|
||
* 函数功能:绑定本地地址和端口
|
||
* 入口参数:sockfd - socket 描述符
|
||
* addr - 本地地址结构体指针
|
||
* addrlen - 地址结构体长度
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已创建且未绑定
|
||
* 函数说明:设置 CH395F 源端口
|
||
*/
|
||
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||
|
||
/*
|
||
* 函数功能:TCP Server 监听
|
||
* 入口参数:sockfd - socket 描述符
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已绑定
|
||
* 函数说明:内部调用 ch395f_tcp_listen,监听 Socket 自身即为数据通道
|
||
*/
|
||
int net_listen(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:TCP Server 接受连接
|
||
* 入口参数:sockfd - 监听 socket 描述符
|
||
* addr - 输出:客户端地址
|
||
* addrlen - 输入输出:地址长度
|
||
* 返回值:新 socket 描述符,失败返回 -1
|
||
* 限定条件:socket 正在监听
|
||
* 函数说明:在非阻塞模式下,如果没有新连接,返回 -1 并设置
|
||
* net_errno 为 NET_ERR_WOULDBLOCK
|
||
*/
|
||
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||
|
||
/*
|
||
* 函数功能:查询监听 Socket 当前是否有可接受的连接(**纯 RAM 读,不发起 RPC**)
|
||
* 入口参数:sockfd - 监听 Socket 描述符 int
|
||
* 出口参数:无
|
||
* 返回值:1 - 有连接可接受;0 - 无(含描述符无效) int
|
||
* 限定条件:net_init() 已调用;任意任务上下文(含 uiTask 等实时性敏感任务)
|
||
* 函数说明:1. 只读 Socket 控制块状态,**不经消息队列、不等 netTask 回执** →
|
||
* 调用方不会被 netTask 的忙碌程度拖住(对比 net_accept:
|
||
* osMessageQueuePut(osWaitForever) + xTaskNotifyWait(portMAX_DELAY),
|
||
* 两者均**无上界**)
|
||
* 2. 判据与 net_accept_locked() 完全一致:单连接模型下监听 Socket 自身
|
||
* 在 CONNECT 事件后转 ESTABLISHED,即"有连接可接受"
|
||
* 3. 用途 = **门控**:无连接时直接跳过 net_accept(),把"每轮一次无谓
|
||
* RPC"降为 0(UI 推流 10 ms 轮询 = 100 msg/s 队列压力的根因)
|
||
* 4. 跨任务读单字:netTask 是唯一写者,最坏两种结果都无害——
|
||
* 晚一轮发现(netTask 每 1 ms 就 net_poll 一次),或扑空
|
||
* (net_accept 返回 -1 + NET_ERR_WOULDBLOCK)
|
||
* 5. 丢 CONNECT 中断由 net_reconcile_tick()(200 ms 对账 + 去抖)自愈,
|
||
* 本函数**不承担**自愈责任
|
||
*/
|
||
int net_can_accept(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:查询监听 Socket 是否处于"应该尝试 accept"的就绪态(**纯 RAM 读,不发起 RPC**)
|
||
* 入口参数:sockfd - 监听 Socket 描述符 int
|
||
* 出口参数:无
|
||
* 返回值:1 - 就绪(LISTENING,或 CLOSED + auto_relisten = 断连待重建态);0 - 不就绪 int
|
||
* 限定条件:net_init() 已调用;任意任务上下文
|
||
* 函数说明:1. N-32(P1 不变量 II):取代 `net_can_accept()`(只认 ESTABLISHED)作为
|
||
* ui_net_sink 的 accept 门控——原门控使 :7003 永不进 `net_accept()`,
|
||
* `net_lost_connect_probe`(丢 CONNECT 中断补 accept,N-30 实证的
|
||
* "数据被吞/425"主根因修复)对该端口等于从未运行
|
||
* 2. 放行 LISTENING:探针与 "closed-but-readable 接受" 都发生在
|
||
* `net_accept_locked` **内部**,门控挡在外面就永远到不了;LISTENING 态
|
||
* accept 要么被探针补中、要么返 WOULDBLOCK,两者均安全
|
||
* 3. 放行 CLOSED + auto_relisten:单连接模型断连后 fd 停在 CLOSED 等
|
||
* relisten(D10 非阻塞重试 / 对账④),此窗口内新 SYN 可能已被芯片
|
||
* 接住 → 放行让 `net_accept_locked` 的状态门自行裁决
|
||
* 4. 与 `net_can_accept` 的语义差异**有意为之**:本函数回答"这个监听器
|
||
* 还在服役吗",而非"这一轮一定有连接"
|
||
* 5. 跨任务读单字,同 `net_can_accept` 的最坏情形论证
|
||
*/
|
||
int net_listener_armed(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:查询 Socket 是否"值得发一次 recv"(**纯 RAM 读,不发起 RPC**)
|
||
* 入口参数:sockfd - Socket 描述符 int
|
||
* 出口参数:无
|
||
* 返回值:1 - 应发 recv(有数据可读,或连接已非 ESTABLISHED 需了结);0 - 不必发 int
|
||
* 限定条件:net_init() 已调用;任意任务上下文
|
||
* 函数说明:1. ESTABLISHED → 看 readable(net_poll 在 RECV_OK 置位、读空清零)
|
||
* 2. **非 ESTABLISHED 一律返回 1**:连接已消失时必须让上层真的 recv 一次
|
||
* 拿到 EOF/错误并自行复位;若把它门掉,"连接已不存在"会被永久藏住
|
||
* (推流侧 g_client 永不复位 → 再也不接受新客户端)
|
||
* 3. 描述符失效(net_get_sock 返回 NULL)同样返回 1 → 让 recv 报 BADF,
|
||
* 走调用方既有的错误分支重建,而不是静默卡死
|
||
* 4. ⚠ **不可作为唯一判据**:readable 只由 RECV_OK 中断置位,而
|
||
* net_reconcile_tick 的三类对账**不含**"芯片 RX 非空但 readable=0"
|
||
* → 中断丢失时本函数会恒返 0。调用方须保留**低频兜底 recv**
|
||
* (ui_net_sink 每 32 轮无条件收一次,最坏延迟 ≈320 ms)
|
||
*/
|
||
int net_can_read(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:TCP Client 发起连接
|
||
* 入口参数:sockfd - socket 描述符
|
||
* addr - 服务器地址
|
||
* addrlen - 地址长度
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已创建
|
||
* 函数说明:连接过程是异步的,需要调用 net_poll() 等待连接完成,
|
||
* 或使用 select() 等待可写事件
|
||
*/
|
||
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||
|
||
/*
|
||
* 函数功能:发送数据(TCP)
|
||
* 入口参数:sockfd - socket 描述符
|
||
* buf - 数据缓冲区
|
||
* len - 数据长度
|
||
* flags - 通常为 0
|
||
* 返回值:实际发送字节数,失败返回 -1
|
||
* 限定条件:TCP 连接已建立,指针非空
|
||
* 函数说明:阻塞等待发送缓冲区空闲,拷贝数据后触发发送
|
||
*/
|
||
int net_send(int sockfd, const void *buf, int len, int flags);
|
||
|
||
/*
|
||
* 函数功能:接收数据(TCP)
|
||
* 入口参数:sockfd - socket 描述符
|
||
* buf - 接收缓冲区
|
||
* len - 缓冲区大小
|
||
* flags - 通常为 0,可设置 NET_MSG_DONTWAIT 非阻塞
|
||
* 返回值:实际接收字节数,0=对端关闭,-1=错误
|
||
* 限定条件:TCP 连接已建立
|
||
* 函数说明:在阻塞模式下,如果没有数据,函数会等待;
|
||
* 在非阻塞模式下,如果没有数据,返回 -1 并设置
|
||
* net_errno 为 NET_ERR_WOULDBLOCK
|
||
*/
|
||
int net_recv(int sockfd, void *buf, int len, int flags);
|
||
|
||
/*
|
||
* 函数功能:接收数据(**带调用方指定超时**的阻塞版,用于分片有界读)
|
||
* 入口参数:sockfd - Socket 描述符
|
||
* buf/len - 接收缓冲与容量
|
||
* timeout_ms - 单次调用在 netTask 内的最长等待(毫秒,>0)
|
||
* 返回值:>0 实际字节数;0 = 对端关闭(EOF);-1 = 真错误(errno 可查);**-2 = 超时无数据**
|
||
* 限定条件:非 netTask 上下文;Socket 已连接
|
||
* 函数说明:为"不能长时间占用 netTask"的调用方(如 lftpd 控制行/数据读)提供
|
||
* **分片**阻塞:每次调用最多占用 netTask timeout_ms,返回 -2 表示这段
|
||
* 时间内无数据,调用方自行累计总预算并决定是否继续(E-02 头阻塞修复)。
|
||
* 超时用独立返回码而非 errno → 无跨任务 errno 竞态。
|
||
*/
|
||
int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms);
|
||
|
||
/*
|
||
* 函数功能:发送 UDP 数据
|
||
* 入口参数:sockfd - socket 描述符
|
||
* buf - 数据缓冲区
|
||
* len - 数据长度
|
||
* flags - 通常为 0
|
||
* dest_addr - 目标地址
|
||
* addrlen - 地址长度
|
||
* 返回值:实际发送字节数,失败返回 -1
|
||
* 限定条件:socket 已创建,指针非空
|
||
* 函数说明:设置目标地址后调用 CH395F 发送
|
||
*/
|
||
int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||
const struct net_sockaddr *dest_addr, int addrlen);
|
||
|
||
/*
|
||
* 函数功能:接收 UDP 数据
|
||
* 入口参数:sockfd - socket 描述符
|
||
* buf - 接收缓冲区
|
||
* len - 缓冲区大小
|
||
* flags - 通常为 0
|
||
* src_addr - 输出:发送方地址
|
||
* addrlen - 输入输出:地址长度
|
||
* 返回值:实际接收字节数,失败返回 -1
|
||
* 限定条件:socket 已创建,指针非空
|
||
* 函数说明:读取 CH395F 接收缓冲区,获取对端地址
|
||
*/
|
||
int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||
struct net_sockaddr *src_addr, int *addrlen);
|
||
|
||
/*
|
||
* 函数功能:关闭 socket
|
||
* 入口参数:sockfd - socket 描述符
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已打开
|
||
* 函数说明:释放 Socket 控制块,TCP 先断开连接
|
||
*/
|
||
int net_close(int sockfd);
|
||
|
||
/*
|
||
* 事件回调 API
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:注册事件回调
|
||
* 入口参数:sockfd - socket 描述符
|
||
* cb - 回调函数
|
||
* arg - 用户参数
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已创建
|
||
* 函数说明:回调在 net_poll 上下文中触发
|
||
*/
|
||
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg);
|
||
|
||
/*
|
||
* 辅助函数
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:获取 **本任务** 最后一次 net_*() 调用失败时的精确错误码
|
||
* 入口参数:无
|
||
* 出口参数:无
|
||
* 返回值:错误码(NET_ERR_xxx);本任务尚无失败记录时为 NET_OK(0)
|
||
* 限定条件:无(任何上下文可调用,含中断——查询为纯本任务索引读)
|
||
* 函数说明:1. **按任务隔离**(2026-09-25 E-03 修复):错误码存在每个任务自己的
|
||
* 槽位里,任务间互不干扰,不存在跨任务覆写竞态——旧实现的单一全局
|
||
* 变量会被 netTask/其他任务的 net 调用交错覆盖,调用方可能读到别人的码
|
||
* 2. 语义:本任务最后一次返回 -1 的 net_*() 调用所对应的精确码;
|
||
* 调用成功时**不清零**(与本 API 历史行为一致,保持向后兼容)
|
||
* 3. 任务句柄槽位用尽时回退到共享槽位(仅影响排障,不影响功能)
|
||
* 4. 超时类场景(net_recv_to)请直接用返回码 -2 判定,不要依赖本接口
|
||
*/
|
||
int net_get_errno(void);
|
||
|
||
/*
|
||
* 函数功能:查询 socket 当前状态(只读快照,可能滞后于 netTask)
|
||
* 返回值:状态值(net_sock_state_t);描述符无效/未占用 → -1
|
||
*/
|
||
int net_sock_state(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:断连重同步——仅把 MCU 侧状态对齐到 LISTENING,不发任何芯片命令
|
||
* 适用场景:芯片"静默回收"(peer 发 FIN 后芯片自行把 Socket 回收回监听
|
||
* 且不发 DISCONNECT 中断,2026-09-22 台架实证)→ MCU 状态滞留
|
||
* ESTABLISHED。调用方须确信连接已死/芯片已回收(如会话超时中止后);
|
||
* 连接仍存活时严禁调用(会把活连接标记成监听态)。
|
||
* 返回值:0 - 已同步(或原本即 LISTENING);-1 - 失败(描述符/队列无效)
|
||
*/
|
||
int net_resync_listen(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:无条件重新监听(芯片侧 open+listen,含 Trap 09 失败重试)
|
||
* 适用场景:断连后需确保监听器确定在位的自愈(监听短暂中断 ~1s,调用方
|
||
* 的重连逻辑须容忍)
|
||
* 返回值:0 - 成功;-1 - 失败
|
||
*/
|
||
int net_relisten(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:将 IP 地址字符串转为网络字节序
|
||
* 入口参数:cp - 点分十进制字符串 "192.168.1.100"
|
||
* 返回值:网络字节序 IP,失败返回 0
|
||
* 限定条件:cp 指针非空
|
||
* 函数说明:不支持域名解析
|
||
*/
|
||
uint32_t net_inet_addr(const char *cp);
|
||
|
||
/*
|
||
* 函数功能:将网络字节序 IP 转为字符串
|
||
* 入口参数: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);
|
||
|
||
#ifndef NET_NO_OS
|
||
/*
|
||
* 函数功能:处理消息队列中的请求(必须在 netTask 主循环中调用)
|
||
* 限定条件:net_init() 已调用
|
||
* 函数说明:处理其他任务通过 net_send/net_recv 等接口发送的请求,
|
||
* 在 netTask 上下文中串行化执行所有 CH395F 操作
|
||
*/
|
||
void net_process_messages(void);
|
||
#endif /* NET_NO_OS */
|
||
|
||
/*
|
||
* 函数功能:获取 Socket 控制块指针(内部使用)
|
||
* 入口参数:sockfd - socket 描述符
|
||
* 返回值:Socket 控制块指针,失败返回 NULL
|
||
*/
|
||
net_sock_t *net_get_sock(int sockfd);
|
||
|
||
/*
|
||
* 函数功能:获取 Socket 本地地址(IP + Port)
|
||
* 入口参数:sockfd - socket 描述符
|
||
* addr - 输出:本地地址
|
||
* addrlen - 输入输出:地址结构体长度
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:socket 已创建或已绑定
|
||
*/
|
||
int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||
|
||
#ifndef NET_NO_OS
|
||
/*
|
||
* 内部 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);
|
||
|
||
/*
|
||
* 函数功能:启动 TCP Server 监听(内部版本,直接操作,不经过消息队列)
|
||
* 入口参数:sockfd - Socket 描述符
|
||
* 返回值:0 成功,-1 失败
|
||
* 限定条件:必须在 netTask 上下文中调用
|
||
*/
|
||
int net_listen_locked(int sockfd);
|
||
#endif /* NET_NO_OS */
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* NET_SOCKET_H */
|