LiteOS通信模组教程05-LiteOS的SAL及socket编程实例

本文介绍了LiteOS的SAL(Socket Abstract Layer)套接字抽象层,旨在提供统一的Socket编程接口,简化物联网设备的网络通信。详细讲解了SAL的优势、Socket基础、字节序转换函数,以及TCP和UDP Socket客户端编程实例,通过实例展示了如何在LiteOS中使用SAL进行TCP和UDP通信。

1. SAL套接字抽象层

SAL全称Socket Abstract Layer,即套接字抽象层,主要作用是对上层应用提供一层统一的 socket 编程接口,屏蔽底层网络硬件的差异。

LiteOS的SAL架构如下:

SAL网络架构

SAL的优势从图中一看即知:

无论底层使用以太网 LwIP协议栈组合,还是使用ESP8266/M26 AT框架组合,经过SAL套接字抽象层之后,对用户提供的接口都是统一的,极大的提高了程序的可移植性。

SAL框架的源码及其实现在SDK中的IoT_LINK_1.0.0\iot_link\network\tcpip目录:

SAL实现源码

除了sal文件夹之外,其余的文件夹分别对应着不同的sal实现,比如esp8266_socket对应的是基于AT框架和ESP8266的SAL实现。

SAL相关的头文件存放在IoT_LINK_1.0.0\iot_link\inc文件夹中,如图:

SAL头文件

  • sal.h:SAL头文件,使用时需包含;
  • sal_imp.h:抽象接口定义头文件;
  • sal_types.h:socket编程中涉及到的类型定义;
  • sal_define.h:socket编程中涉及到的宏定义;
  • link_endian.h:socket编程中的大小端字节序转换函数定义;

2. Socket编程基础

2.1. Socket概述

Socket称为套接字,本质上是一种文件描述符,所以socket通信的过程和操作文件的方法基本类似。

TCP/IP协议族的传输层中,分为有连接的,可靠的TCP传输方式,和无连接的,不可靠的UDP传输方式,所以Socket分为两种:

  • 流式Socket(SOCK_STREAM):提供可靠的、面向连接的通信流,使用TCP协议;
  • 数据报Socket(SOCK_DGRAM):提供一种无连接的服务,使用UDP协议;

2.2. Socket结构体

一个标准的Socket应该包括以下五部分:

  • 协议类型
  • 目的IP
  • 目的端口
  • 源ip
  • 源端口

SAL提供了两种socket的结构体用于存放数据,sockaddr结构体和sockaddr_in结构体,定义均在sal_types.h文件中。

sockaddr结构体的定义如下:

struct sockaddr
{
   
   
    sa_family_t     sa_family;      /* address family, AF_xxx   */
    char            sa_data[14];    /* 14 bytes of protocol address */
};

参数说明如下:

  • sa_family:地址族,一般为AF_INET,表示IPv4协议;
  • sa_data:包含了源ip、源端口、目的ip、目的端口;

sockaddr_in结构体的定义如下:

struct sockaddr_in
{
   
   
    sa_family_t sin_family;             /* AF_INET */
    in_port_t sin_port;                 /* Port number.  */
    struct in_addr sin_addr;            /* Internet address.  */
    unsigned char sin_zero[8];          /* Pad to size of `struct sockaddr'.  */
};

sockaddr结构体将所有的ip和端口信息都放在了sa_data中,不利用编程,而sockaddr_in结构体本质上和sockaddr结构体一样,但是将目的ip和目的端口分离出来,容易编程,所以一般在使用的时候有如下技巧:

使用sockaddr_in结构体赋值,作为参数传递时强制转换为sockaddr类型传递

2.3. 字节序转换函数

在sockaddr_in结构体中填写sin_port和sin_addr这两个值时,需要注意:

  • in_port_tuint16_t类型;
  • sin_addruint32_t类型;

这样就涉及到了两个转换问题:

  • ip地址的转换

ip地址通常是一个字符串,比如"192.168.1.100",但是此处需要转换为一个uint32_t类型的数据,SAL提供了一个转换函数,在之前提到的link_endian.h文件中,函数如下:


  • 字节序的转换

字节序分为大端存储和小端存储,为了保证统一性,屏蔽硬件差异,需要将ip地址和端口的值转换为网络字节序,SAL提供了本地字节序和网络字节序的互相转换函数,在link_endian.h文件中,其中h表示host主机,n表示network网络字节序

htonl(unsigned long int hostlong);
htons(unisgned short int hostshort);
ntohl(unsigned long int netlong);
ntohs(unsigned short int netshort);

3. AT框架和SAL配置及开启

本实验中我们使用ESP8266 AT框架 SAL进行实验,所以需要开启使能AT框架和SAL。

3.1. AT框架开启

关于AT框架具体的剖析,可以阅读上一篇教程

在工程目录下的.sdkconfig中手动配置开启驱动框架(串口使用)和AT框架:

AT框架开启

实验中使用的是ESP8266,所以还需要配置路由器的SSID和PASSWD,在SDK目录中IoT_LINK_1.0.0\iot_link\network\tcpip\esp8266_socket目录下, 打开esp8266_socket_imp.h文件:

在其中设置ESP8266连接的热点名称和密码,这里我的设置如下:

热点设置

最后,需要修改同文件夹下的esp8266_socket_imp.mk文件,将图中标出的两处TOP_DIR改为SDK_DIR:

makefile文件

makefile设置

3.2. SAL开启

SAL默认是未开启的,需要在工程目录下的.sdkconfig中手动配置开启:

使能esp8266实现的sal

其中CONFIG_TCPIP_ENABLE = y需要自己添加,CONFIG_TCPIP_TYPE宏定义的值目前支持,可以根据自己的需求选择:

  • “lwip_socket”
  • “linux_socket”
  • “macos_socket”
  • “esp8266_socket”
  • “none”

注意:两个宏定义必须同时存在且使能,SAL才会生效。

3.3. SAL自动初始化

使能了SAL之后,系统会自动进行初始化,在SDK目录中的IoT_LINK_1.0.0\iot_link下的link_main.c文件中即可看到:

SAL自动初始化

4. TCP Socket客户端编程实例

4.1. TCP服务端的建立

在本实验中,TCP Server使用网络调试助手模拟,在本机8000端口开启一个TCP服务器,如图:

TCP服务端

4.2. SAL提供的Socket客户端编程API

建立socket

API原型如下:

int sal_socket(int domain, int type, int protocol);

参数说明如下:

参数 说明 常用值
domain 协议或地址族 AF_INET,表示IPv4
type socket类型 SOCK_STREAM,表示TCP
SOCK_DGRAM,表示UDP
protocol 使用的
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值