ZYNQ学习之旅--PS_ETH(tcp_server)

简介

随着 5G 的兴起,万物互联成为将来发展的一个方向,更多的设备将具备联网的功能,将数据上传到云端。得益于 TCP/IP 协议的优越性,该协议已成为当前应用的主流网络协议。在嵌入式网络设备中由于受到硬件资源的限制,实现完整的 TCP/IP 协议十分困难,这就需要一种特殊的实现方式,LWIP 作为一种轻量级的 TCP/IP 协议实现方式充分满足了这一要求。

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简介

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 地址。

BD设计

在这里插入图片描述
这里将网口选上。
在这里插入图片描述
串口也选上,即可。

关键部分软件代码

int start_application()
{
	struct tcp_pcb *pcb;
	err_t err;
	unsigned port = 6;

	/* create new TCP PCB structure */
	pcb = tcp_new();
	if (!pcb) {
		xil_printf("Error creating PCB. Out of Memory\n\r");
		return -1;
	}

	/* bind to specified @port */
	err = tcp_bind(pcb, IP_ADDR_ANY, port);
	if (err != ERR_OK) {
		xil_printf("Unable to bind to port %d: err = %d\n\r", port, err);
		return -2;
	}

	/* we do not need any arguments to callback functions */
	tcp_arg(pcb, NULL);

	/* listen for connections */
	pcb = tcp_listen(pcb);
	if (!pcb) {
		xil_printf("Out of memory while tcp_listen\n\r");
		return -3;
	}

	/* specify callback to use for incoming connections */
	tcp_accept(pcb, accept_callback);

	xil_printf("TCP echo server started @ port %d\n\r", port);
	//err = tcp_write(pcb, s, strlen(s), 1);
	return 0;
}

可以看到这个板子作为服务器开始监听远程连接。

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;
}

这里是回调函数,可以看到这里将接收到的数据原封不动的写回到客户端,这里我增加了一个串口打印出数据。
在这里插入图片描述
可以看到网口环回了,串口相应的也打印出了数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值