随着 5G 的兴起,万物互联成为将来发展的一个方向,更多的设备将具备联网的功能,将数据上传到云端。得益于 TCP/IP 协议的优越性,该协议已成为当前应用的主流网络协议。在嵌入式网络设备中由于受到硬件资源的限制,实现完整的 TCP/IP 协议十分困难,这就需要一种特殊的实现方式,LWIP 作为一种轻量级的 TCP/IP 协议实现方式充分满足了这一要求。
TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)体系结构是指能够在多个不同网络间实现的协议簇。该协议簇是在美国国防高级研究计划局(Defense Advanced Research Projects Agency,DARPA)所资助的实验性 ARPARNET 分组交换网络、无线电分组网络和卫星分组网络上研究开发成功的。网络部分瘫痪时仍保持较强的工作能力和灵活性。这种应用环境导致了一系列协议的出现,从而使不同类型的终端和网络间能够进行有效通信。实际上,Internet 已经成为全球计算机互联的主要体系结构,而 TCP/IP 协议是 Internet 的代名词,是将异种网络、不同设备互联起来,进行正常数据通信的格式和大家遵守的约定。
TCP/IP 协议包括两部分:传输控制协议和网际协议。TCP/IP 的通信任务组织成 5 个相对独立的层次:应用层、传输层、互联网层(对应 OSI 的网络层)、网络接口层和物理层,其中网络接口层和物理层常称为物理网层。各层功能如下:
(1)应用层:应用程序通过这一层访问网络,常见 FTP、HTTP、DNS 和 TELNET协议; (2)传输层:TCP 协议和 UDP 协议; (3)网络层:IP 协议,ARP、RARP 协议,ICMP 协议等,网络层负责相邻计算机之间的通信 (4)网络接口层:是 TCP/IP 协议的基层(最低层),负责数据帧的发送和接收。
lwip 是瑞典计算机科学院(SICS)的 Adam Dunkels 开发的一个小型开源的TCP/IP 协议栈。LwIP 是 Light Weight (轻型)IP 协议,有无操作系统的支持都可以运行。LwIP 实现的重点是在保持 TCP 协议主要功能的基础上减少对 RAM 的占用,它只需十几 KB 的 RAM 和 40K 左右的 ROM 就可以运行,这使 LwIP 协议栈适合在低端的嵌入式系统中使用。lwIP 协议栈主要关注的是怎么样减少内存的使用和代码的大小,这样就可以让 lwIP 适用于资源有限的小型平台例如嵌入式系统。 其主要特性如下: (1)支持多网络接口下的 IP 转发; (2)支持 ICMP 协议; (3)包括实验性扩展的 UDP(用户数据报协议); (4)包括阻塞控制、RTT 估算、快速恢复和快速转发的 TCP(传输控制协议); (5)提供专门的内部回调接口(Raw API),用于提高应用程序性能; (6)可选择的 Berkeley 接口 API (在多线程情况下使用) ; (7)在最新的版本中支持 ppp; (8) 新版本中增加了的 IP fragment 的支持; (9) 支持 DHCP 协议,动态分配 ip 地址。
这里将网口选上。 串口也选上,即可。
可以看到这个板子作为服务器开始监听远程连接。
err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) { static int connection = 1; /* set the receive callback for this connection */ tcp_recv(newpcb, recv_callback); /* just use an integer number indicating the connection id as the callback argument */ tcp_arg(newpcb, (void*)(UINTPTR)connection); /* increment for subsequent accepted connections */ connection++; return ERR_OK; }这是接收到了数据去绑定相应的回调函数。
err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { /* do not read the packet if we are not in ESTABLISHED state */ if (!p) { tcp_close(tpcb); tcp_recv(tpcb, NULL); return ERR_OK; } /* indicate that the packet has been received */ tcp_recved(tpcb, p->len); /* echo back the payload */ /* in this case, we assume that the payload is < TCP_SND_BUF */ if (tcp_sndbuf(tpcb) > p->len) { err = tcp_write(tpcb, p->payload, p->len, 1); //printf("%s\n",tpcb->local_ip); printf("%s\n",p->payload); } else xil_printf("no space in tcp_sndbuf\n\r"); /* free the received pbuf */ pbuf_free(p); return ERR_OK; }这里是回调函数,可以看到这里将接收到的数据原封不动的写回到客户端,这里我增加了一个串口打印出数据。 可以看到网口环回了,串口相应的也打印出了数据。