学会Zynq(21)TCP轮询机制(polling)示例

FPGA 同时被 2 个专栏收录
136 篇文章 279 订阅
30 篇文章 52 订阅

前面我们已经学习了TCP的所有发送、接收和各种回调函数。本文将介绍最后一部分,TCP的轮询机制。

在前面TCP发送Hello World的实例中,我们是在main函数的while循环中每隔1s调用一次数据发送函数。本文的实例将利用轮询机制完成同样的功能。


SDK程序设计

本文根据TCP client模式下发送hello world的程序改编(server模式改动也类似)。主要差别在user_udp.c文件中, 其余文件代码基本相同(main.c的while循环中无需调用send_data函数发送数据)。

#include "user_tcp.h"

#define SEND_SIZE 12

static struct tcp_pcb *connected_pcb = NULL;
int tcp_poll_cnt = 0;
char sendBuffer[12]="Hello World!";

//--------------------------------------------------
//               TCP轮询的回调函数
//--------------------------------------------------
err_t tcp_poll_callback(void * arg, struct tcp_pcb * tpcb)
{
	tcp_poll_cnt++;     //统计发送数据的次数
	xil_printf("poll int:%d\r\n", tcp_poll_cnt);
	send_data();

	return ERR_OK;
}

//--------------------------------------------------
//             TCP连接成功的回调函数
//--------------------------------------------------
err_t tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err)
{
	xil_printf("txperf: Connected to iperf server\r\n");

	connected_pcb = tpcb;   //存储连接的TCP状态

	tcp_nagle_disable(connected_pcb);
	tcp_arg(tpcb, NULL);    //指定应该传递回调函数的参数
	//设置轮询回调函数tcp_sent_callback
	tcp_poll(connected_pcb, tcp_poll_callback, 2);

	xil_printf("Connect Success.\r\n");
	return ERR_OK;
}

//--------------------------------------------------
//              TCP PCB初始化函数
//--------------------------------------------------
int tcp_send_init()
{
	struct tcp_pcb *pcb;
	struct ip_addr ipaddr;
	err_t err;
	u16_t port;

	//创建新的TCP PCB
	pcb = tcp_new();
	if (!pcb) {
		xil_printf("txperf: Error creating PCB. Out of Memory\r\n");
		return -1;
	}

	IP4_ADDR(&ipaddr, 192, 168, 1, 100);   //服务器的IP地址
	port = 7;					           //服务器的默认端口

    //连接主机,连接建立后调用回调函数tcp_connected_callback
	err = tcp_connect(pcb, &ipaddr, port, tcp_connected_callback);
	if (err != ERR_OK) {
		xil_printf("txperf: tcp_connect returned error: %d\r\n", err);
		return err;
	}
	xil_printf("%d\r\n",err);

	return 0;
}

//--------------------------------------------------
//                TCP数据发送函数
//--------------------------------------------------
void send_data(void)
{
	err_t err;
	struct tcp_pcb *tpcb = connected_pcb;

	if (!connected_pcb)
			return;

	err = tcp_write(tpcb, sendBuffer, SEND_SIZE, 3);
	if (err != ERR_OK) {
		xil_printf("txperf: Error on tcp_write: %d\r\n", err);
		connected_pcb = NULL;
		return;
	}
	err = tcp_output(tpcb);
	if (err != ERR_OK) {
		xil_printf("txperf: Error on tcp_output: %d\r\n",err);
		return;
	}
}

在连接成功的回调函数tcp_connected_callback中,使用tcp_poll函数绑定TCP的轮询回调函数tcp_poll_callback。当连接处于空闲状态时(即没有发送或接收数据),lwIP将周期性的调用轮询回调函数。

tcp_toll指定轮询应用程序时应调用的回调函数和轮询间隔。TCP有一个粗略的计时器,大概一秒钟发出两次信号,轮询间隔时间和此有关。此处设置为2,则表示应用程序大约每(2/2=)1秒轮询一次。本例在轮询回调函数中发送数据。

这种机制类似看门狗定时器,以解决长时间处于空闲状态的连接;也可以作为一种等待内存变为可用状态的方法。比如当内存不可用导致tcp_write的调用失败时,应用程序可以在连接空闲了一段时间后,使用轮询功能再次调用tcp_write。

测试结果如下,串口信息中可看到进入轮询回调函数的次数:

在这里插入图片描述


总结

止此,lwIP中所有与UDP、TCP相关的函数即使用方法都介绍完毕,且给出了实例的形式。希望对各位有帮助。

  • 5
    点赞
  • 2
    评论
  • 14
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值