Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the SAL and socket programming method of LiteOS

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "what is the SAL and socket programming method of LiteOS". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the SAL and socket programming method of LiteOS".

1. SAL socket abstraction layer

The full name of SAL is Socket Abstract Layer, that is, socket abstraction layer. Its main function is to provide a unified socket programming interface for upper applications and shield the differences of underlying network hardware.

The SAL architecture of LiteOS is as follows:

The advantages of SAL can be seen at a glance:

Whether the bottom layer uses the combination of Ethernet + LwIP protocol stack or the combination of ESP8266/M26+AT framework, after the SAL socket abstraction layer, the interface provided by users is unified, which greatly improves the portability of the program.

The source code of the SAL framework and its implementation can be found in the IoT_LINK_1.0.0\ iot_link\ network\ tcpip directory in SDK:

Except for the sal folder, the other folders correspond to different sal implementations, such as esp8266_socket, which corresponds to the SAL implementation based on the AT framework and ESP8266.

SAL-related header files are stored in the IoT_LINK_1.0.0\ iot_link\ inc folder, as shown in the figure:

Sal.h:SAL header file, which needs to be included when using

Sal_imp.h: abstract interface definition header file

Type definitions involved in sal_types.h:socket programming

Macro definition involved in sal_define.h:socket programming

Definition of byte order conversion function for large and small ends in link_endian.h:socket programming

2. Socket programming basis 2.1. Overview of Socket

Socket is called a socket and is essentially a file descriptor, so the process of socket communication is basically similar to the way you manipulate files.

The transport layer of the TCP/IP protocol family is divided into connected, reliable TCP transmission and connectionless, unreliable UDP transmission, so Socket is divided into two types:

Streaming Socket (SOCK_STREAM): provides reliable, connection-oriented traffic, using the TCP protocol

Datagram Socket (SOCK_DGRAM): provides a connectionless service using the UDP protocol

2.2. Socket structure

A standard Socket should include the following five parts:

Protocol Typ

Objective IP

Destination port

Source ip

Source port

SAL provides two socket structures for storing data, the sockaddr structure and the sockaddr_in structure, both of which are defined in the sal_types.h file.

The definition of sockaddr structure is as follows:

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

The parameters are described as follows:

Sa_family: address family, usually AF_INET, which represents the IPv4 protocol

Sa_data: contains source ip, source port, destination ip, destination port

The definition of sockaddr_in structure is as follows:

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'. * /}

The sockaddr structure puts all the ip and port information in the sa_data without using programming, while the sockaddr_in structure is essentially the same as the sockaddr structure, but it is easy to program by separating the destination ip from the destination port, so you generally have the following skills when using it:

Use sockaddr_in structure assignment to cast to sockaddr type when passed as a parameter.

2.3. Byte order conversion function

When filling in the values of sin_port and sin_addr in the sockaddr_in structure, you should pay attention to:

In_port_t is of type uint16_t

Sin_addr is of type uint32_t

This involves two conversion issues:

Translation of ip address

The ip address is usually a string, such as "192.168.1.100", but here you need to convert it to data of type uint32_t. SAL provides a conversion function, which in the link_endian.h file mentioned earlier is as follows:

Conversion of byte order

Byte order is divided into large-end storage and small-end storage. In order to ensure unity and shield hardware differences, it is necessary to convert the values of ip addresses and ports into network byte order. SAL provides a mutual conversion function between local byte order and network byte order. In the link_endian.h file, h represents host host and n represents network network byte order:

Htonl (unsigned long int hostlong); htons (unisgned short int hostshort); ntohl (unsigned long int netlong); ntohs (unsigned short int netshort); 3. AT framework and SAL configuration and opening

In this lab, we use ESP8266+AT framework + SAL to experiment, so we need to open the enable AT framework and SAL.

3.1. AT frame is open

For a specific analysis of the AT framework, you can read the previous tutorial.

Manually configure the open driver framework (serial port is used) and AT framework in .sdkconfig under the project directory:

ESP8266 is used in the lab, so you also need to configure the SSID and PASSWD of the router. In the IoT_LINK_1.0.0\ iot_link\ network\ tcpip\ esp8266_socket directory in the SDK directory, open the esp8266_socket_imp.h file:

Set the hotspot name and password for the ESP8266 connection. Here, my settings are as follows:

Finally, you need to modify the esp8266_socket_imp.mk file in the same folder and change the two TOP_DIR marked in the figure to SDK_DIR:

3.2. SAL is enabled

SAL is not enabled by default. You need to manually configure it in .sdkconfig in the project directory:

CONFIG_TCPIP_ENABLE = y needs to be added by yourself. The values defined by CONFIG_TCPIP_TYPE macros are currently supported, and you can choose them according to your needs:

"lwip_socket"

"linux_socket"

"macos_socket"

"esp8266_socket"

"none"

Note: two macro definitions must exist and enabled at the same time for SAL to take effect.

3.3. SAL automatic initialization

Once SAL is enabled, the system initializes automatically, which can be seen in the link_main.c file under IoT_LINK_1.0.0\ iot_link in the SDK directory:

4. TCP Socket client programming example 4.1. Establishment of TCP server

In this lab, TCP Server uses the network debugging assistant to simulate and open a TCP server on native port 8000, as shown in the figure:

4.2. Socket client programming API provided by SAL to establish socket

The prototype of API is as follows:

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

The parameters are described as follows:

Parameter description common value domain protocol or address family AF_INET, indicating IPv4typesocket type SOCK_STREAM and TCP

SOCK_DGRAM, which indicates the protocol number 0 used by UDPprotocol, returns a socket descriptor int type value using the default protocol number, and-1 indicates a failed connection to the server socket

The prototype of API is as follows:

Int sal_connect (int sockfd, const struct sockaddr * addr,socklen_t addrlen)

The parameters are described as follows:

Parameter indicates that the sockfd descriptor created by sockfd successfully addrsockaddr structure pointer addrlensockaddr structure length socket sends data

The prototype of API is as follows:

Int sal_send (int sockfd,const void * buf,size_t len,int flags)

The parameters are described as follows:

Parameters indicate that the sockfd descriptor BUF created by sockfd successfully sends data len sends data length flags sends or receives tags, which is generally set to 0socket to receive data (non-blocking)

The prototype of API is as follows:

Int sal_recv (int sockfd,void * buf,size_t len,int flags)

The parameters are described as follows:

Parameter description: sockfd descriptor created by sockfd successfully buf receive data buffer len receive data buffer length flags send or receive flag, generally set to 0 to turn off socket

The prototype of API is as follows:

Int sal_closesocket (int sockfd)

The parameters are described as follows:

The parameter indicates that sockfd successfully created the sockfd descriptor 4. 3. TCP client programming based on SAL

Open the HelloWorld project you created earlier (if not, you can refer to the first tutorial to create a new one), create the following folder sal_test_demo, and create a new test file sal_tcp_demo.c in this folder:

Edit the following:

Note that the server_ip and server_port should correspond to the actual situation of the server!

# include # include # define server_port 8000#define server_ip "192.168.0.101" static int sal_tcp_demo_entry () {int sockfd; / * create TCP socket * / sockfd = sal_socket (AF_INET, SOCK_STREAM, 0); if (sockfd < 0) {printf ("TCP Socket create fail.\ r\ n"); return-1 } else {printf ("TCP Socket create ok.\ r\ n");} / * Connect to the server * / struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons (server_port); server_addr.sin_addr.s_addr = inet_addr (server_ip) While (- 1 = = sal_connect (sockfd, (struct sockaddr*) & server_addr, sizeof (struct sockaddr)) {/ / connection fails, then automatically reconnect printf ("connect server fail, repeat...\ r\ n") after 1 second; osal_task_sleep (1000);} printf ("connect server ok.\ r\ n"); int nbytes; char buf [] = "hello server!" / / send data to server nbytes = sal_send (sockfd, buf, sizeof (buf), 0); if (nbytes < 0) {printf ("send dat% s fail.\ r\ n", buf); return-1;} else {printf ("send [% d] bytes:% s.\ r\ n", nbytes, buf) } / / wait to receive server data char recv_buf [50] = {0}; while (- 1 = = (nbytes = sal_recv (sockfd, recv_buf, 50,0)); printf ("recv [% d] bytes:% s.\ r\ n", nbytes, recv_buf); / / close socket sal_closesocket (sockfd); printf ("TCP socket closed.\ r\ n"); return 0 } int standard_app_demo_main () {osal_task_create ("sal_tcp_demo", sal_tcp_demo_entry,NULL,0x800,NULL,12); return 0;}

Then add the file path to user_demo.mk:

# example for sal_tcp_demo ifeq ($(CONFIG_USER_DEMO), "sal_tcp_demo") user_demo_src = ${wildcard $(TOP_DIR) / targets/STM32L431_BearPi/Demos/sal_test_demo/sal_tcp_demo.c} endif

The location is as follows:

Finally, configure and select the demo file in .sdkconfig:

Then compile, download, and see the serial output (if you make sure that the TCP server is turned on):

In the TCP server software, you can also see:

Send data at the server, and you can see that the client has received it at the serial port:

5. UDP Socket client programming example 5.1. Establishment of UDP server

In this lab, UDP Server uses the network debugging assistant to simulate and open a UDP server on native port 8000, as shown in the figure:

5.2. Socket client programming API connection server socket provided by SAL

The prototype of API is as follows:

Int sal_connect (int sockfd, const struct sockaddr * addr,socklen_t addrlen)

The parameters are described as follows:

Parameter indicates that sockfd successfully created sockfd descriptor addrsockaddr structure pointer addrlensockaddr structure length to send data

The prototype of API is as follows:

Int sal_sendto (int sockfd, const void * dataptr, size_t size, int flags, const struct sockaddr * to, socklen_t tolen)

The parameters are described as follows:

Parameter description: sockfd descriptor created by sockfd successfully dataptr data pointer to be sent size sending packet data size flags sending or receiving flag, generally set to 0addrsockaddr structure pointer addrlensockaddr structure length to receive data

The prototype of API is as follows:

Int sal_recvfrom (int sockfd, void * mem, size_t len, int flags, struct sockaddr * from, socklen_t * fromlen)

The parameters are described as follows:

Parameters indicate that sockfd successfully created sockfd descriptor mem receive buffer data pointer size receive data size flags send or receive flag, generally set to 0addrsockaddr structure pointer addrlensockaddr structure length to turn off socket

The prototype of API is as follows:

Int sal_closesocket (int sockfd)

The parameters are described as follows:

Parameter indicates that sockfd successfully created the sockfd descriptor 5. 3. 0. UDP client programming based on SAL

Open the HelloWorld project you created earlier (if not, you can refer to the first tutorial to create a new one), create the following folder sal_test_demo, and create a new test file sal_udp_demo.c in this folder:

Edit the following:

Note that the server_ip and server_port should correspond to the actual situation of the server!

# include # include # define server_port 8000#define server_ip "192.168.0.101" static int sal_udp_demo_entry () {int sockfd; / * create udp socket * / sockfd = sal_socket (AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) {printf ("udp Socket create fail.\ r\ n"); return-1 } else {printf ("udp Socket create ok.\ r\ n");} / * Server information * / struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons (server_port); server_addr.sin_addr.s_addr = inet_addr (server_ip); / * send data to server * / int nbytes Char buf [] = "hello server!"; nbytes = sal_sendto (sockfd, buf, sizeof (buf), 0, (struct sockaddr*) & server_addr, sizeof (struct sockaddr)); if (nbytes < 0) {printf ("send dat% s fail.\ r\ n", buf); return-1;} else {printf ("send [% d] bytes:% s.\ r\ n", nbytes, buf) } / * waiting to receive server data * / char recv_buf [50] = {0}; while (- 1 = = (nbytes = sal_recvfrom (sockfd, recv_buf, 50,0, (struct sockaddr*) & server_addr, sizeof (struct sockaddr); printf ("recv [% d] bytes:% s.\ r\ n", nbytes, recv_buf); / * close socket * / sal_closesocket (sockfd) Printf ("udp socket closed.\ r\ n"); return 0;} int standard_app_demo_main () {osal_task_create ("sal_udp_demo", sal_udp_demo_entry,NULL,0x800,NULL,12); return 0;}

Then add the file path to user_demo.mk:

# example for sal_udp_demo ifeq ($(CONFIG_USER_DEMO), "sal_udp_demo") user_demo_src = ${wildcard $(TOP_DIR) / targets/STM32L431_BearPi/Demos/sal_test_demo/sal_udp_demo.c} endif

The location is as follows:

Finally, configure and select the demo file in .sdkconfig:

Then compile, download, and see the serial output (if you make sure that the UDP server is turned on):

In the UDP server software, you can also see:

Send data at the server, and you can see that the client has received it at the serial port:

Thank you for your reading, the above is the content of "what is LiteOS's SAL and socket programming methods". After the study of this article, I believe you have a deeper understanding of what LiteOS's SAL and socket programming methods are, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report