TCP可以正常使用
This commit is contained in:
105
Drivers/BSP/NET/net_config.h
Normal file
105
Drivers/BSP/NET/net_config.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 模块名称:Network Configuration
|
||||
* 模块功能:网络子系统配置宏定义,包括最大Socket数量、缓冲区大小、
|
||||
* 超时时间等参数配置
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
*/
|
||||
|
||||
#ifndef __NET_CONFIG_H
|
||||
#define __NET_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 最大支持的 Socket 数量(CH395F 支持 0~7)
|
||||
*/
|
||||
#ifndef NET_MAX_SOCKETS
|
||||
#define NET_MAX_SOCKETS 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP Server 多连接模式配置
|
||||
* 监听 Socket 索引和数据 Socket 起始索引
|
||||
*/
|
||||
#ifndef NET_TCP_SERVER_LISTEN_SOCK
|
||||
#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
|
||||
|
||||
/*
|
||||
* 缓冲区大小配置
|
||||
*/
|
||||
#ifndef NET_SEND_BUF_SIZE
|
||||
#define NET_SEND_BUF_SIZE 4096 /* 发送缓冲区大小(字节) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_RECV_BUF_SIZE
|
||||
#define NET_RECV_BUF_SIZE 4096 /* 接收缓冲区大小(字节) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 超时时间配置(毫秒)
|
||||
* 0 = 无限等待(阻塞模式)
|
||||
*/
|
||||
#ifndef NET_CONNECT_TIMEOUT_MS
|
||||
#define NET_CONNECT_TIMEOUT_MS 5000 /* 连接超时 */
|
||||
#endif
|
||||
|
||||
#ifndef NET_ACCEPT_TIMEOUT_MS
|
||||
#define NET_ACCEPT_TIMEOUT_MS 0 /* 接受连接超时(0=无限等待) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_SEND_TIMEOUT_MS
|
||||
#define NET_SEND_TIMEOUT_MS 1000 /* 发送超时 */
|
||||
#endif
|
||||
|
||||
#ifndef NET_RECV_TIMEOUT_MS
|
||||
#define NET_RECV_TIMEOUT_MS 0 /* 接收超时(0=无限等待) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP KeepAlive 配置
|
||||
*/
|
||||
#ifndef NET_KEEPALIVE_IDLE_MS
|
||||
#define NET_KEEPALIVE_IDLE_MS 7200000 /* KeepAlive 空闲时间(默认2小时) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_KEEPALIVE_INTVL_MS
|
||||
#define NET_KEEPALIVE_INTVL_MS 75000 /* KeepAlive 探测间隔(默认75秒) */
|
||||
#endif
|
||||
|
||||
#ifndef NET_KEEPALIVE_CNT
|
||||
#define NET_KEEPALIVE_CNT 9 /* KeepAlive 探测次数(默认9次) */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* select/poll 最大 fd 数量
|
||||
*/
|
||||
#ifndef NET_SELECT_MAX_FDS
|
||||
#define NET_SELECT_MAX_FDS NET_MAX_SOCKETS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 轮询延时配置(毫秒)
|
||||
*/
|
||||
#ifndef NET_POLL_DELAY_MS
|
||||
#define NET_POLL_DELAY_MS 1 /* 非阻塞轮询延时 */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_CONFIG_H */
|
||||
319
Drivers/BSP/NET/net_select.c
Normal file
319
Drivers/BSP/NET/net_select.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* 模块名称:Network Select Implementation
|
||||
* 模块功能:I/O 多路复用实现,包括 select 和 poll 模式,
|
||||
* 用于同时监控多个 Socket 的读写事件
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
*/
|
||||
|
||||
#include "net_select.h"
|
||||
#include "net_socket.h"
|
||||
#include "ch395f.h"
|
||||
|
||||
/*
|
||||
* 私有函数声明区
|
||||
*/
|
||||
static int check_socket_readable(int sockfd);
|
||||
static int check_socket_writable(int sockfd);
|
||||
static int check_socket_error(int sockfd);
|
||||
|
||||
/*
|
||||
* 公共函数实现区
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(select 模式)
|
||||
*/
|
||||
int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
net_fd_set *exceptfds, net_timeval *timeout)
|
||||
{
|
||||
uint32_t start_tick;
|
||||
uint32_t timeout_ms = 0;
|
||||
net_fd_set result_read = {0};
|
||||
net_fd_set result_write = {0};
|
||||
net_fd_set result_except = {0};
|
||||
int ready_count = 0;
|
||||
int i;
|
||||
|
||||
/* 计算超时时间 */
|
||||
if (timeout != NULL)
|
||||
{
|
||||
timeout_ms = (uint32_t)(timeout->tv_sec * 1000) +
|
||||
(uint32_t)(timeout->tv_usec / 1000);
|
||||
}
|
||||
|
||||
start_tick = HAL_GetTick();
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 轮询所有 Socket */
|
||||
net_poll();
|
||||
|
||||
ready_count = 0;
|
||||
|
||||
/* 检查哪些 Socket 有事件 */
|
||||
for (i = 0; i < nfds && i < NET_MAX_SOCKETS; i++)
|
||||
{
|
||||
net_sock_t *sock = net_get_sock(i);
|
||||
|
||||
if (sock == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 检查可读事件 */
|
||||
if (readfds != NULL && NET_FD_ISSET(i, readfds))
|
||||
{
|
||||
if (check_socket_readable(i))
|
||||
{
|
||||
NET_FD_SET(i, &result_read);
|
||||
ready_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 检查可写事件 */
|
||||
if (writefds != NULL && NET_FD_ISSET(i, writefds))
|
||||
{
|
||||
if (check_socket_writable(i))
|
||||
{
|
||||
NET_FD_SET(i, &result_write);
|
||||
ready_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 检查异常事件 */
|
||||
if (exceptfds != NULL && NET_FD_ISSET(i, exceptfds))
|
||||
{
|
||||
if (check_socket_error(i))
|
||||
{
|
||||
NET_FD_SET(i, &result_except);
|
||||
ready_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 有事件就绪,返回 */
|
||||
if (ready_count > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* 超时检查 */
|
||||
if (timeout != NULL)
|
||||
{
|
||||
if (timeout_ms > 0 &&
|
||||
(HAL_GetTick() - start_tick) >= timeout_ms)
|
||||
{
|
||||
break; /* 超时返回 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 短暂延时避免忙等 */
|
||||
HAL_Delay(NET_POLL_DELAY_MS);
|
||||
}
|
||||
|
||||
/* 复制结果 */
|
||||
if (readfds != NULL)
|
||||
{
|
||||
readfds->fd_bits = result_read.fd_bits;
|
||||
}
|
||||
if (writefds != NULL)
|
||||
{
|
||||
writefds->fd_bits = result_write.fd_bits;
|
||||
}
|
||||
if (exceptfds != NULL)
|
||||
{
|
||||
exceptfds->fd_bits = result_except.fd_bits;
|
||||
}
|
||||
|
||||
return ready_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(poll 模式)
|
||||
*/
|
||||
int net_poll_events(net_pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
uint32_t start_tick;
|
||||
int ready = 0;
|
||||
int i;
|
||||
|
||||
if (fds == NULL || nfds <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
start_tick = HAL_GetTick();
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 轮询 */
|
||||
net_poll();
|
||||
|
||||
ready = 0;
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
fds[i].revents = 0;
|
||||
|
||||
/* 检查 fd 有效性 */
|
||||
if (fds[i].fd < 0 || fds[i].fd >= NET_MAX_SOCKETS)
|
||||
{
|
||||
fds[i].revents |= NET_POLLNVAL;
|
||||
ready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
net_sock_t *sock = net_get_sock(fds[i].fd);
|
||||
|
||||
if (sock == NULL)
|
||||
{
|
||||
fds[i].revents |= NET_POLLNVAL;
|
||||
ready++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 检查可读 */
|
||||
if (fds[i].events & NET_POLLIN)
|
||||
{
|
||||
if (check_socket_readable(fds[i].fd))
|
||||
{
|
||||
fds[i].revents |= NET_POLLIN;
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 检查可写 */
|
||||
if (fds[i].events & NET_POLLOUT)
|
||||
{
|
||||
if (check_socket_writable(fds[i].fd))
|
||||
{
|
||||
fds[i].revents |= NET_POLLOUT;
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 检查错误 */
|
||||
if (check_socket_error(fds[i].fd))
|
||||
{
|
||||
fds[i].revents |= NET_POLLERR;
|
||||
ready++;
|
||||
}
|
||||
|
||||
/* 检查挂起(连接断开) */
|
||||
if (sock->state == NET_SOCK_STATE_TCP_ACCEPT ||
|
||||
sock->state == NET_SOCK_STATE_CLOSED)
|
||||
{
|
||||
fds[i].revents |= NET_POLLHUP;
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ready > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* 超时检查 */
|
||||
if (timeout >= 0)
|
||||
{
|
||||
if ((HAL_GetTick() - start_tick) >= (uint32_t)timeout)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Delay(NET_POLL_DELAY_MS);
|
||||
}
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
/*
|
||||
* 私有函数实现区
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否可读
|
||||
* 返回值:1 可读,0 不可读
|
||||
*/
|
||||
static int check_socket_readable(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
uint16_t recv_len;
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 监听 Socket 有新连接时可读 */
|
||||
if (sock->state == NET_SOCK_STATE_LISTENING)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 已建立连接的 Socket 有数据可读 */
|
||||
if (sock->state == NET_SOCK_STATE_ESTABLISHED)
|
||||
{
|
||||
recv_len = ch395f_get_recv_len(sockfd);
|
||||
if (recv_len > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否可写
|
||||
* 返回值:1 可写,0 不可写
|
||||
*/
|
||||
static int check_socket_writable(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 已建立连接的 Socket 发送缓冲区空闲时可写 */
|
||||
if (sock->state == NET_SOCK_STATE_ESTABLISHED)
|
||||
{
|
||||
if (sock->send_ready)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:检查 Socket 是否有错误
|
||||
* 返回值:1 有错误,0 无错误
|
||||
*/
|
||||
static int check_socket_error(int sockfd)
|
||||
{
|
||||
net_sock_t *sock;
|
||||
|
||||
/* 无效 fd 视为错误 */
|
||||
if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
sock = net_get_sock(sockfd);
|
||||
if (sock == NULL)
|
||||
{
|
||||
return 1; /* 未使用的 Socket 视为错误 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
114
Drivers/BSP/NET/net_select.h
Normal file
114
Drivers/BSP/NET/net_select.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 模块名称:Network Select API
|
||||
* 模块功能:I/O 多路复用接口,支持 select 和 poll 模式,
|
||||
* 用于同时监控多个 Socket 的读写事件
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
*/
|
||||
|
||||
#ifndef __NET_SELECT_H
|
||||
#define __NET_SELECT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "net_types.h"
|
||||
#include "net_config.h"
|
||||
|
||||
/*
|
||||
* 文件描述符集合
|
||||
* 每个位对应一个 socket 描述符 (0~7)
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t fd_bits; /* 位掩码 */
|
||||
} net_fd_set;
|
||||
|
||||
/*
|
||||
* 时间结构体
|
||||
*/
|
||||
typedef struct {
|
||||
long tv_sec; /* 秒 */
|
||||
long tv_usec; /* 微秒 */
|
||||
} net_timeval;
|
||||
|
||||
/*
|
||||
* poll 事件结构体
|
||||
*/
|
||||
typedef struct {
|
||||
int fd; /* socket 描述符 */
|
||||
short events; /* 请求的事件 */
|
||||
short revents; /* 实际发生的事件 */
|
||||
} net_pollfd;
|
||||
|
||||
/*
|
||||
* poll 事件掩码
|
||||
*/
|
||||
#define NET_POLLIN 0x0001 /* 可读 */
|
||||
#define NET_POLLOUT 0x0004 /* 可写 */
|
||||
#define NET_POLLERR 0x0008 /* 错误 */
|
||||
#define NET_POLLHUP 0x0010 /* 挂起 */
|
||||
#define NET_POLLNVAL 0x0020 /* 无效请求 */
|
||||
|
||||
/*
|
||||
* fd_set 操作宏
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:清空 fd_set
|
||||
*/
|
||||
#define NET_FD_ZERO(fdset) ((fdset)->fd_bits = 0)
|
||||
|
||||
/*
|
||||
* 函数功能:将 fd 加入 fd_set
|
||||
*/
|
||||
#define NET_FD_SET(fd, fdset) ((fdset)->fd_bits |= (1U << (fd)))
|
||||
|
||||
/*
|
||||
* 函数功能:将 fd 从 fd_set 移除
|
||||
*/
|
||||
#define NET_FD_CLR(fd, fdset) ((fdset)->fd_bits &= ~(1U << (fd)))
|
||||
|
||||
/*
|
||||
* 函数功能:检查 fd 是否在 fd_set 中
|
||||
*/
|
||||
#define NET_FD_ISSET(fd, fdset) (((fdset)->fd_bits & (1U << (fd))) != 0)
|
||||
|
||||
/*
|
||||
* I/O 多路复用 API
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(select 模式)
|
||||
* 入口参数:nfds - 最大 fd + 1(通常为 NET_MAX_SOCKETS)
|
||||
* readfds - 可读事件集合,NULL 表示不关心
|
||||
* writefds - 可写事件集合,NULL 表示不关心
|
||||
* exceptfds - 异常事件集合,NULL 表示不关心
|
||||
* timeout - 超时时间,NULL 表示无限等待
|
||||
* 返回值:就绪的 fd 数量,0=超时,-1=错误
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:此函数会调用 net_poll() 轮询所有 Socket,
|
||||
* 并检查哪些 Socket 有指定的事件发生。
|
||||
*/
|
||||
int net_select(int nfds, net_fd_set *readfds, net_fd_set *writefds,
|
||||
net_fd_set *exceptfds, net_timeval *timeout);
|
||||
|
||||
/*
|
||||
* 函数功能:I/O 多路复用(poll 模式)
|
||||
* 入口参数:fds - net_pollfd 数组
|
||||
* nfds - 数组元素数量
|
||||
* timeout - 超时时间(毫秒),-1 表示无限等待
|
||||
* 返回值:就绪的 fd 数量,0=超时,-1=错误
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:与 select 类似,但使用 pollfd 结构体数组,
|
||||
* 更灵活,支持更多事件类型。
|
||||
*/
|
||||
int net_poll_events(net_pollfd *fds, int nfds, int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_SELECT_H */
|
||||
1219
Drivers/BSP/NET/net_socket.c
Normal file
1219
Drivers/BSP/NET/net_socket.c
Normal file
File diff suppressed because it is too large
Load Diff
227
Drivers/BSP/NET/net_socket.h
Normal file
227
Drivers/BSP/NET/net_socket.h
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 模块名称: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"
|
||||
|
||||
/*
|
||||
* 网络初始化接口
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式)
|
||||
* 入口参数:ip - 本地 IP 地址字符串 "192.168.1.100",NULL 使用 DHCP
|
||||
* mask - 子网掩码字符串 "255.255.255.0",NULL 使用默认
|
||||
* gateway - 网关地址字符串 "192.168.1.1",NULL 使用默认
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:SPI2 已正确初始化
|
||||
* 函数说明:必须在所有网络操作之前调用
|
||||
*/
|
||||
int net_init(const char *ip, const char *mask, const char *gateway);
|
||||
|
||||
/*
|
||||
* 函数功能:轮询所有 Socket 状态(必须在主循环中调用)
|
||||
* 返回值:有事件发生的 socket 数量
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:此函数处理所有 Socket 的中断事件,更新状态,
|
||||
* 并触发事件回调。在非阻塞模式下必须定期调用。
|
||||
*/
|
||||
int net_poll(void);
|
||||
|
||||
/*
|
||||
* 核心 Socket API
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:创建 socket
|
||||
* 入口参数:domain - 地址族,仅支持 AF_INET
|
||||
* type - SOCK_STREAM(TCP) 或 SOCK_DGRAM(UDP)
|
||||
* protocol - 通常为 0
|
||||
* 返回值:socket 描述符 (0~7),失败返回 -1
|
||||
* 限定条件:net_init() 已调用
|
||||
*/
|
||||
int net_socket(int domain, int type, int protocol);
|
||||
|
||||
/*
|
||||
* 函数功能:绑定本地地址和端口
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* addr - 本地地址结构体指针
|
||||
* addrlen - 地址结构体长度
|
||||
* 返回值:0 成功,-1 失败
|
||||
*/
|
||||
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
|
||||
/*
|
||||
* 函数功能:TCP Server 监听
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* backlog - 最大等待连接数(多连接模式下为数据 Socket 数量)
|
||||
* 返回值:0 成功,-1 失败
|
||||
* 限定条件:socket 已绑定
|
||||
*/
|
||||
int net_listen(int sockfd, int backlog);
|
||||
|
||||
/*
|
||||
* 函数功能: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);
|
||||
|
||||
/*
|
||||
* 函数功能: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);
|
||||
|
||||
/*
|
||||
* 函数功能:发送 UDP 数据
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* buf - 数据缓冲区
|
||||
* len - 数据长度
|
||||
* flags - 通常为 0
|
||||
* dest_addr - 目标地址
|
||||
* addrlen - 地址长度
|
||||
* 返回值:实际发送字节数,失败返回 -1
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
struct net_sockaddr *src_addr, int *addrlen);
|
||||
|
||||
/*
|
||||
* 函数功能:关闭 socket
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:0 成功,-1 失败
|
||||
*/
|
||||
int net_close(int sockfd);
|
||||
|
||||
/*
|
||||
* 事件回调 API
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:注册事件回调
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* cb - 回调函数
|
||||
* arg - 用户参数
|
||||
* 返回值:0 成功,-1 失败
|
||||
*/
|
||||
int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg);
|
||||
|
||||
/*
|
||||
* 辅助函数
|
||||
*/
|
||||
|
||||
/*
|
||||
* 函数功能:获取 socket 最后错误码
|
||||
* 返回值:错误码(NET_ERR_xxx)
|
||||
*/
|
||||
int net_get_errno(void);
|
||||
|
||||
/*
|
||||
* 函数功能:将 IP 地址字符串转为网络字节序
|
||||
* 入口参数:cp - 点分十进制字符串 "192.168.1.100"
|
||||
* 返回值:网络字节序 IP
|
||||
*/
|
||||
uint32_t net_inet_addr(const char *cp);
|
||||
|
||||
/*
|
||||
* 函数功能:将网络字节序 IP 转为字符串
|
||||
* 入口参数:addr - 网络字节序 IP
|
||||
* buf - 输出缓冲区(至少 16 字节)
|
||||
* 返回值:buf 指针
|
||||
*/
|
||||
char *net_inet_ntoa(uint32_t addr, char *buf);
|
||||
|
||||
/*
|
||||
* 函数功能:端口字节序转换(主机序 -> 网络序)
|
||||
*/
|
||||
uint16_t net_htons(uint16_t hostshort);
|
||||
|
||||
/*
|
||||
* 函数功能:端口字节序转换(网络序 -> 主机序)
|
||||
*/
|
||||
uint16_t net_ntohs(uint16_t netshort);
|
||||
|
||||
/*
|
||||
* 函数功能:IP 地址字节序转换(主机序 -> 网络序)
|
||||
*/
|
||||
uint32_t net_htonl(uint32_t hostlong);
|
||||
|
||||
/*
|
||||
* 函数功能:IP 地址字节序转换(网络序 -> 主机序)
|
||||
*/
|
||||
uint32_t net_ntohl(uint32_t netlong);
|
||||
|
||||
/*
|
||||
* 函数功能:获取 Socket 控制块指针(内部使用)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:Socket 控制块指针,失败返回 NULL
|
||||
*/
|
||||
net_sock_t *net_get_sock(int sockfd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_SOCKET_H */
|
||||
175
Drivers/BSP/NET/net_types.h
Normal file
175
Drivers/BSP/NET/net_types.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 模块名称:Network Types
|
||||
* 模块功能:网络子系统类型定义,包括地址结构体、Socket状态、
|
||||
* 事件类型、Socket控制块等
|
||||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-18
|
||||
* 修改记录:
|
||||
*/
|
||||
|
||||
#ifndef __NET_TYPES_H
|
||||
#define __NET_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "net_config.h"
|
||||
|
||||
/*
|
||||
* 地址族定义
|
||||
*/
|
||||
#define NET_AF_INET 2 /* IPv4 */
|
||||
#define NET_AF_INET6 10 /* IPv6(未支持) */
|
||||
#define NET_AF_UNSPEC 0 /* 未指定 */
|
||||
|
||||
/*
|
||||
* Socket 类型定义
|
||||
*/
|
||||
#define NET_SOCK_STREAM 1 /* TCP */
|
||||
#define NET_SOCK_DGRAM 2 /* UDP */
|
||||
|
||||
/*
|
||||
* 协议号定义
|
||||
*/
|
||||
#define NET_IPPROTO_TCP 6
|
||||
#define NET_IPPROTO_UDP 17
|
||||
#define NET_IPPROTO_ICMP 1
|
||||
|
||||
/*
|
||||
* 特殊地址定义
|
||||
*/
|
||||
#define NET_INADDR_ANY 0 /* 任意地址 */
|
||||
#define NET_INADDR_NONE 0xFFFFFFFF /* 无效地址 */
|
||||
|
||||
/*
|
||||
* 接收标志定义
|
||||
*/
|
||||
#define NET_MSG_DONTWAIT 0x01 /* 非阻塞模式 */
|
||||
|
||||
/*
|
||||
* 网络字节序转换宏
|
||||
*/
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define NET_htonl(x) (x)
|
||||
#define NET_htons(x) (x)
|
||||
#define NET_ntohl(x) (x)
|
||||
#define NET_ntohs(x) (x)
|
||||
#else
|
||||
#define NET_htonl(x) (((uint32_t)(x) << 24) | \
|
||||
(((uint32_t)(x) & 0xFF00) << 8) | \
|
||||
(((uint32_t)(x) & 0xFF0000) >> 8) | \
|
||||
((uint32_t)(x) >> 24))
|
||||
#define NET_htons(x) (((uint16_t)(x) << 8) | ((uint16_t)(x) >> 8))
|
||||
#define NET_ntohl(x) NET_htonl(x)
|
||||
#define NET_ntohs(x) NET_htons(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 套接字地址结构体
|
||||
*/
|
||||
struct net_sockaddr {
|
||||
uint16_t sa_family; /* 地址族 */
|
||||
char sa_data[14]; /* 地址数据 */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPv4 套接字地址结构体
|
||||
*/
|
||||
struct net_sockaddr_in {
|
||||
uint16_t sin_family; /* 地址族,必须为 AF_INET */
|
||||
uint16_t sin_port; /* 端口号(网络字节序) */
|
||||
struct {
|
||||
uint32_t s_addr; /* IP 地址(网络字节序) */
|
||||
} sin_addr;
|
||||
char sin_zero[8]; /* 填充字节 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Socket 错误码定义
|
||||
*/
|
||||
#define NET_OK 0 /* 成功 */
|
||||
#define NET_ERR -1 /* 通用错误 */
|
||||
#define NET_ERR_BADF -2 /* 无效 socket 描述符 */
|
||||
#define NET_ERR_INVAL -3 /* 无效参数 */
|
||||
#define NET_ERR_NOMEM -4 /* 内存不足 */
|
||||
#define NET_ERR_NOTCONN -5 /* 未连接 */
|
||||
#define NET_ERR_ISCONN -6 /* 已连接 */
|
||||
#define NET_ERR_WOULDBLOCK -7 /* 非阻塞模式下操作未完成 */
|
||||
#define NET_ERR_CONNRESET -8 /* 连接被重置 */
|
||||
#define NET_ERR_TIMEDOUT -9 /* 操作超时 */
|
||||
#define NET_ERR_NOSPACE -10 /* 发送缓冲区无空间 */
|
||||
#define NET_ERR_BUSY -11 /* 操作未完成(CH395F BUSY) */
|
||||
|
||||
/*
|
||||
* Socket 状态枚举
|
||||
*/
|
||||
typedef enum {
|
||||
NET_SOCK_STATE_CLOSED = 0, /* 未使用 */
|
||||
NET_SOCK_STATE_CREATED, /* 已创建,未绑定 */
|
||||
NET_SOCK_STATE_BOUND, /* 已绑定 */
|
||||
NET_SOCK_STATE_LISTENING, /* TCP Server 监听中(仅监听 Socket) */
|
||||
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;
|
||||
|
||||
/*
|
||||
* 网络事件类型枚举
|
||||
*/
|
||||
typedef enum {
|
||||
NET_EVENT_CONNECTED = 0, /* 连接建立 */
|
||||
NET_EVENT_DISCONNECTED, /* 连接断开 */
|
||||
NET_EVENT_DATA_RECEIVED, /* 收到数据 */
|
||||
NET_EVENT_SEND_COMPLETE, /* 发送完成 */
|
||||
NET_EVENT_TIMEOUT, /* 操作超时 */
|
||||
NET_EVENT_ERROR, /* 错误发生 */
|
||||
} net_event_t;
|
||||
|
||||
/*
|
||||
* 事件回调函数类型定义
|
||||
* 参数:sockfd - socket 描述符
|
||||
* event - 事件类型
|
||||
* arg - 用户参数
|
||||
*/
|
||||
typedef void (*net_event_cb_t)(int sockfd, net_event_t event, void *arg);
|
||||
|
||||
/*
|
||||
* Socket 控制块结构体
|
||||
* 每个 socket 对应一个控制块,管理其状态和参数
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t ch395_sock; /* CH395F 物理 Socket 索引 (0~7) */
|
||||
net_sock_state_t state; /* Socket 状态 */
|
||||
uint8_t type; /* SOCK_STREAM / SOCK_DGRAM */
|
||||
uint8_t in_use; /* 是否在用标志 */
|
||||
uint16_t local_port; /* 本地端口(主机序) */
|
||||
uint16_t remote_port; /* 远端端口(主机序) */
|
||||
uint32_t remote_ip; /* 远端 IP(网络字节序) */
|
||||
uint8_t remote_ip_arr[4]; /* 远端 IP 数组(低字节在前) */
|
||||
|
||||
/* 事件回调(可选) */
|
||||
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;
|
||||
|
||||
/* 统计信息 */
|
||||
uint32_t recv_bytes; /* 累计接收字节数 */
|
||||
uint32_t send_bytes; /* 累计发送字节数 */
|
||||
} net_sock_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_TYPES_H */
|
||||
Reference in New Issue
Block a user