嵌入式上位机开发入门(八):RT-Thread 的 Socket 代码借鉴

张开发
2026/5/19 8:27:42 15 分钟阅读
嵌入式上位机开发入门(八):RT-Thread 的 Socket 代码借鉴
目录一、前言二、at_socket.h 核心宏定义三、Server 端实现分析四、Client 端实现分析五、总结六、结尾一、前言大家好这里是Hello_Embed。在写出基于 FreeRTOS 的 Socket 代码前可以借鉴优秀的 RT-Thread 代码示例。“at_socket_demo” 是一个 RT-Thread 示例程序这个程序是使用rt-thread studio创建的不必关注如何创建这个程序。我们只是参考它的代码分析它如何实现 AT 模块的 Socket 封装。二、at_socket.h 核心宏定义RT-Thread 通过宏定义将标准 Socket API 封装为 AT 模块专用的函数#definesocket(domain,type,protocol)at_socket(domain,type,protocol)#defineclosesocket(socket)at_closesocket(socket)#defineshutdown(socket,how)at_shutdown(socket,how)#definebind(socket,name,namelen)at_bind(socket,name,namelen)#defineconnect(socket,name,namelen)at_connect(socket,name,namelen)#definesendto(socket,data,size,flags,to,tolen)at_sendto(socket,data,size,flags,to,tolen)#definesend(socket,data,size,flags)at_send(socket,data,size,flags)#definerecvfrom(socket,mem,len,flags,from,fromlen)at_recvfrom(socket,mem,len,flags,from,fromlen)#definegetsockopt(socket,level,optname,optval,optlen)at_getsockopt(socket,level,optname,optval,optlen)#definesetsockopt(socket,level,optname,optval,optlen)at_setsockopt(socket,level,optname,optval,optlen)#definegethostbyname(name)at_gethostbyname(name)#definegetaddrinfo(nodename,servname,hints,res)at_getaddrinfo(nodename,servname,hints,res)#definefreeaddrinfo(ai)at_freeaddrinfo(ai)通过这种封装上层代码可以直接使用标准 Socket API底层自动调用 AT 命令实现通信。三、Server 端实现分析第一步分配 socket按照流程先分配 socketintat_socket(intdomain,inttype,intprotocol){sockalloc_socket(socket_type);// ...returnsock-socket;}alloc_socket分配结构体返回值就是 socket 描述符可以通过返回值找到对应的结构体此时的结构体还没有绑定任何 IP、端口信息第二步绑定查看at_bind的实现intat_bind(intsocket,conststructsockaddr*name,socklen_tnamelen){// sockaddr *name 中存储本地 IP 与端口并保存在 socket 中sockaddr_to_ipaddr_port(name,input_ipaddr,port);sock-listen.portport;// 记录本地端口}RT-Thread 支持多个网卡如何选择网卡每个网卡有自己的 IPlocal_ipaddrbind 函数里 name 参数有 IPinput_ipaddr 使用 name 参数的 IP 去寻找网卡第三步监听找到at_listen函数intat_listen(intsocket,intbacklog){// struct at_socket *sock 含有本地端口if(sock-ops-at_listen(sock,backlog)0){result-RT_ERROR;goto__exit;}}每一种 WiFi 模块都有自己的结构体staticconststructat_socket_opsesp32_socket_ops{esp32_socket_connect,esp32_socket_close,esp32_socket_send,esp32_domain_resolve,esp32_socket_set_event_cb,// ...};重点关注esp8266_socket_listenif(at_obj_exec_cmd(device-client,resp,ATCIPSERVER1, %d,listen_port)0){result-RT_ERROR;goto__exit;}主要功能就是设置 WiFi 模块用于 TCP Server 功能并监听 port。第四步接收 Clientintat_accept(intsocket,structsockaddr*name,socklen_t*namelen){// 保存客户端信息IP/PORT在 name// 1. 阻塞// 2. 被唤醒解析数据提取 client 信息}第五步、第六步收发数据、关闭连接下篇继续讲解。四、Client 端实现分析第一步分配 socket 结构体与 Server 端相同调用at_socket分配结构体。第二步连接 Server 端可以注意到 Client 端没有绑定在连接热点时可以获取 IP但还缺少 port 信息。连接函数如下intat_connect(intsocket,conststructsockaddr*name,socklen_tnamelen){// 在这里获取到目的的 IP 与 port// 函数内部必然会// 1. 分配本地 port// 2. AT 命令连接if(sock-ops-at_connect(sock,ipstr,remote_port,sock-type,RT_TRUE)0){// 连接失败}}这与 Server 端监听用到的 ops 是相同的会使用各种 AT 命令创建连接。连接之后就可以开始收发数据了。五、总结宏定义封装通过宏定义将标准 Socket API 映射为 AT 命令函数Server 端流程分配 socket → 绑定 → 监听 → 接收 Client → 收发数据 → 关闭Client 端流程分配 socket → 连接 → 收发数据 → 关闭ops 结构体每种 WiFi 模块都有独立的 ops 结构体实现统一的 AT 命令接口无需手动绑定Client 端连接热点时可自动获取 IP六、结尾本篇借鉴了 RT-Thread 的 AT Socket 代码分析了 Server 端与 Client 端的实现思路。下一篇将继续借鉴学习** Server 端与 Client 端的数据收发**。Hello_Embed继续带你从原理到实践掌握嵌入式上位机开发的核心技能敬请关注

更多文章