MS-RTOS 网络子系统
本章将介绍 MS-RTOS 网络子系统开发。
网络实现
网络实现是 MS-RTOS 网络子系统对不同实现方法的 TCP/IP 协议网络通信技术的抽象。
不同的网络实现(如 TCP/IP 协议栈和 ESP8266 等有线、无线通信模块)提供了不同的 API 和数据类型,MS-RTOS 为了保证上层应用能使用统一标准的 BSD/socket
套接字 API 进行网络编程,MS-RTOS 网络子系统对网络实现进行了抽象。
多套网络实现能够在 MS-RTOS 中共存,目前 MS-RTOS 已经支持了三种网络实现:
- lwIP 轻量级 TCP/IP 协议栈,加入了多 IP 支持
- ESP8266/ESP32
- SIM800/SIM900(2G)和 SIM7000/SIM7020(NB-Iot LTE)
网络实现示例
以 lwIP 协议栈为例,需要定义一个 ms_net_impl_t
对象及实现相关的网络实现操作 ms_net_impl_ops_t
:
// socket 设备驱动程序操作
static ms_io_driver_ops_t ms_lwip_socket_drv_ops = {
.type = MS_IO_DRV_TYPE_SOCK,
.open = __ms_lwip_socket_open,
.close = __ms_lwip_socket_close,
.write = __ms_lwip_socket_write,
.read = __ms_lwip_socket_read,
.ioctl = __ms_lwip_socket_ioctl,
.fcntl = __ms_lwip_socket_fcntl,
.poll = __ms_lwip_socket_poll,
};
// socket 设备驱动程序
static ms_io_driver_t ms_lwip_socket_drv = {
.nnode = {
.name = MS_LWIP_SOCKET_DRV_NAME,
},
.ops = &ms_lwip_socket_drv_ops,
};
// 网络实现操作
static ms_net_impl_ops_t ms_lwip_net_impl_ops = {
.sock_drv_name = MS_LWIP_SOCKET_DRV_NAME,
.socket = (ms_net_socket_func_t)__ms_lwip_socket,
.accept = (ms_net_accept_func_t)__ms_lwip_accept,
.bind = (ms_net_bind_func_t)lwip_bind,
.getpeername = (ms_net_getpeername_func_t)lwip_getpeername,
.getsockname = (ms_net_getsockname_func_t)lwip_getsockname,
.getsockopt = (ms_net_getsockopt_func_t)lwip_getsockopt,
.setsockopt = (ms_net_setsockopt_func_t)lwip_setsockopt,
.connect = (ms_net_connect_func_t)lwip_connect,
.listen = (ms_net_listen_func_t)lwip_listen,
.shutdown = (ms_net_shutdown_func_t)lwip_shutdown,
.recv = (ms_net_recv_func_t)lwip_recv,
.recvfrom = (ms_net_recvfrom_func_t)lwip_recvfrom,
.recvmsg = (ms_net_recvmsg_func_t)lwip_recvmsg,
.send = (ms_net_send_func_t)lwip_send,
.sendmsg = (ms_net_sendmsg_func_t)lwip_sendmsg,
.sendto = (ms_net_sendto_func_t)lwip_sendto,
.if_indextoname = (ms_net_if_indextoname_func_t)lwip_if_indextoname,
.if_nametoindex = (ms_net_if_nametoindex_func_t)lwip_if_nametoindex,
.gethostbyname_addrtype = (ms_net_gethostbyname_addrtype_func_t)netconn_gethostbyname_addrtype,
.gethostname = (ms_net_gethostname_func_t)__ms_lwip_gethostname,
.sethostname = (ms_net_sethostname_func_t)__ms_lwip_sethostname,
.getdnsserver = (ms_net_getdnsserver_func_t)__ms_lwip_getdnsserver,
.setdnsserver = (ms_net_setdnsserver_func_t)__ms_lwip_setdnsserver,
};
// 网络实现对象
static ms_net_impl_t ms_lwip_net_impl = {
.nnode = {
.name = MS_LWIP_NET_IMPL_NAME,
},
.ops = &ms_lwip_net_impl_ops,
};
// 初始化 lwIP 网络实现
ms_err_t ms_lwip_net_init(void (*init_done_callback)(ms_ptr_t arg), ms_ptr_t arg)
{
ms_err_t err;
// 初始化 lwIP 协议栈
tcpip_init(init_done_callback, arg);
// 注册 lwIP 网络实现
err = ms_net_impl_register(&ms_lwip_net_impl);
if (err == MS_ERR_NONE) {
// 注册 lwIP socket 设备驱动
err = ms_io_driver_register(&ms_lwip_socket_drv);
if (err == MS_ERR_NONE) {
ms_lwip_inited = MS_TRUE;
}
}
return err;
}
相关 API
// 获得默认的网络实现
ms_net_impl_t *ms_net_impl_default(void);
// 通过名字查找网络实现
ms_net_impl_t *ms_net_impl_find(const char *name);
// 注册一个网络实现
ms_err_t ms_net_impl_register(ms_net_impl_t *net_impl);
// 注册一个指定网络实现的 socket 设备,并与传入的 dev_ctx 关联
int ms_net_socket_attach(const char *net_impl_name, ms_ptr_t dev_ctx);
// sockaddr 转 ipaddr 与 port
void ms_net_sockaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *ipaddr, ms_uint16_t *port);
// ipaddr 与 port 转 sockaddr
void ms_net_ipaddr_port_to_sockaddr(union sockaddr_aligned *saddr, ip_addr_t *ipaddr, ms_uint16_t port);
// 构建 IPv4 地址
void ms_net_ip_addr4(ip_addr_t *ipaddr, ms_uint8_t ip0, ms_uint8_t ip1, ms_uint8_t ip2, ms_uint8_t ip3);
// 设置为任意的 IP 地址
void ms_net_ip_addr_set_any(ms_bool_t is_ipv6, ip_addr_t *ipaddr);
相关命令
命令 | 介绍 | 参数 |
---|---|---|
nets | 查看注册的网络实现 | 无 |
lwipstat | 查看 lwIP 协议栈的统计信息 | 无 |
netifs | 查看 lwIP 网络接口的信息 | 无 |