从零实现 LWIP 三(TCP客户端服务端、静态IP)

从零实现 LWIP 一(配置过程)

从零实现 LWIP 二(UDP、无DHCP)

从零实现 LWIP 四(一对一 UDP、TCP客户端 DHCP 网线热插拔和自动重新连接)

上一章实现了UDP功能,本章将实现TCP功能。

TCP和UDP不同的是,TCP需要先建立连接,LWIP驱动50%都是TCP的,10%是UDP,可见TCP要复杂的多。但是使用起来,TCP并没有感觉复杂很多。


进入正题,先介绍下我的硬件设备以及软件版本

硬件:正点原子阿波罗STM32F429IGT6,外部PHY芯片 LAN8720

软件:keilv5, cubemx 4.23.0

尝试过最新的cubemx 5.6.0,不习惯那种交互界面,此外HAL库由于升级,会跟之前低版本生成的HAL库不兼容。


TCP client是客户端、TCP server是服务端。客户端主动去连接服务端,与服务端建立连接后,服务端也可以向客户端发送数据。

client是得知道目标地址,进行连接。只能一对一的去连接服务器,因此只有一个tcp控制块。

但是server是允许所有地址连接自己,但什么时候有IP连接自己并不知道。所以server是可以一对多的接入client,因此可能会不止有一个控制块。
想要发送数据也要在有连接成功后才可以进行。得知哪个IP已经连接上,可以通过server注册的连接回调函数(static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err))的入口参数newpcb获取信息,newpcb是TCP的协议控制块
那么我们在服务端接入回调函数中,就可以通过此newpcb得知很多关于这个连接的信息,最关键的当然就是得知remote(遥远的)ip和port是多少,也就是与之相连的客户端IP、port。


TCPclient 、server都需要两个回调函数,
一个是接入回调函数,是在TCP建立连接后进入的,该回调函数在TCP client、server初始化时绑定;
另一个是接收回调函数是接收到数据时进入的,该回调函数在TCP建立连接后绑定。

UDP client、server因为不需要连接,则只需要一个接收回调函数。


对 TCP, 通过向 output 函数传递一个指向连续内存区域的指针发送数据。TCP/IP
协议栈会将这些数据分割成适当大小的信息包,然后放入传输队列。

当发送 UDP 包时,应用
程序必须明确的分配一个缓冲区并填上数据。TCP/IP 协议栈会在调用 output 函数时立即发
送这个 UDP 包。


LwIP 使用两个周期性定时器,周期分别为 200ms 和 500ms。
细粒度定时器(fine grained timer)tcp_timer_fine()会遍历每一个 TCP PCB,检查是否存在应该被发送的被延迟的 ACKs, 如果延迟 ACK 标志被设置,一个空的 TCP ACK 应答段被发送,并且标志被清除。
粗粒度定时器在 tcp_timer_coarse()函数里实现,同样扫描 PCB 列表。对每一个 PCB,将遍历未应答报文段列表报文段被重发并且重发超时加倍

说的简单点就是细粒度定时器是用来给别人回复应答包的,粗粒度定时器是检查没有收到应答包的,然后重发。

原子是在自己的应用程序中开启定时器调用这两个定时器的处理,但我并没有这么做,也能够正常使用功能,原因我就不懂了。望大神留言指点。


关于本地IP、掩码、网关、port,因为我们现在没有用到DHCP,用的是静态IP,通过查看void MX_LWIP_Init(void)就看到了,在初始化的时候就是把我们设置的IP、掩码、网关配置进全局网络接口结构体-gnetif中。在LWIP的执行函数中就是不断调用这个结构体进行处理。

至于port端口则是在udp或tcp初始化设置到控制块udp_pcb、tcp_pcb中,若是tcp client就立即连接,若是tcp server则开启监听,若连接的IP、掩码、网关能对上,再到TCP client、server的tcp_pcb端口号也能对上,那么就连接成功了,进入tcp client、server的接入回调函数。


先实现tcp client。

下载工程后,打开网络调试助手以及串口调试器。先打开TCP server后打开开发板或者复位开发板,两方都显示连接上了。

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第1张图片

此时tcp的client已经和server建立了连接了,我们可以互发数据了。

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第2张图片

收发数据完毕后,断开连接会发生什么?

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第3张图片

 


实现tcp server。

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第4张图片

打开tcp client连接

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第5张图片

互发数据:

从零实现 LWIP 三(TCP客户端服务端、静态IP)_第6张图片


 

总结:

会者不难 难者不会,现在看起来不难啊,但是当时真的没有头绪,乱糟糟的。多看看代码,多看看资料会清晰一些。

本来DHCP已经做完了,但是现在我有新的目标了,我得去做linux了,无论是成功还是失败我都会回来继续写完DHCP的。

朋友,祝我成功吧


 

参考资料:原子的STM32F429开发指南HAL.pdf、LwIP协议栈的设计与实现_中文译稿.pdf 

STM32CubeMX系列教程27:ETH

stm32+lwip(一):使用STM32CubeMX生成项目(必看)

STM32407+LAN8720A+LWIP 实现TCP Client

你可能感兴趣的:(嵌入式编程,网络)