学会Zynq(19)TCP发送Hello World(server模式)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FPGADesigner/article/details/88776615

上文介绍了用TCP发送“Hello World”的实例,工作在client模式下。本文实现同样的功能,但让TCP工作在server模式下。把开发板当作服务器,远程主机为客服端访问服务器,实现被动连接。TCP client和TCP server在lwIP中的连接流程和区别可参考本系列前面与lwIP相关的文章。


SDK程序设计

大部分代码和上一个实例相同。main函数的while循环中仍然是根据连接标志来启动数据发送函数,每秒发送一个“Hello World”。

	while(1) {
		/* call tcp timer every 250ms */
		if(TcpTmrFlag)
		{
			tcp_tmr();
			TcpTmrFlag = 0;
		}
		xemacif_input(netif);     //将MAC队列中的packets传输到lwIP栈中
		if (tcp_client_connected) {  //连接成功则发送数据
			sleep(1);
			send_data();
		}	
	}

与上一个实例的主要区别在user_tcp.c文件,代码如下:

#include "user_tcp.h"

#define SEND_SIZE 12
#define local_port 8080

static struct tcp_pcb *connected_pcb = NULL;
volatile unsigned tcp_client_connected = 0;
char sendBuffer[12]="Hello World!";

//--------------------------------------------------
//             TCP连接成功的回调函数
//--------------------------------------------------
err_t connect_accept_callback(void *arg, struct tcp_pcb *tpcb, err_t err)
{
	xil_printf("tcp_server: Connection Accepted\r\n");

	connected_pcb = tpcb;   //存储连接的TCP状态
	tcp_client_connected = 1;
	tcp_nagle_disable(connected_pcb);

	return ERR_OK;
}

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

	/*  创建新的TCP PCB  */
	pcb = tcp_new();
	if (!pcb) {
		xil_printf("txperf: Error creating PCB. Out of Memory\r\n");
		return -1;
	}
	/*  绑定本地端口  */
	err = tcp_bind(pcb, IP_ADDR_ANY, local_port);
	if (err != ERR_OK) {
	    xil_printf("tcp_server: Unable to bind to port %d: err = %d\r\n", local_port, err);
	    return -2;
	}
    /*  监听连接  */
	tcp_arg(pcb, NULL);
	pcb = tcp_listen(pcb);
	if (!pcb) {
		xil_printf("tcp_server: Out of memory while tcp_listen\r\n");
		return -3;
	}
	/*  设置accept回调函数  */
	tcp_accept(pcb, connect_accept_callback);

	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工作在服务器模式,将开发板当作服务器,被动等待客户端请求连接。


TCP客户端

我们回顾一下本系列第11篇中介绍的TCP被动连接方法:

  1. 调用pcb_new创建一个pcb。
  2. (可选)调用tcp_arg将应用程序中特定的值于PCB关联在一起。
  3. 调用tcp_bind函数指定本地IP地址和端口。
  4. 调用tcp_listentcp_listen_with_backlog,这些函数将释放作为参数的PCB,并返回一个更小的监听PCB,如“tcp_new = tcp_listen(tpcb);”。
  5. 调用tcp_accept指定新连接到来时要调用的函数。

tcp_send_init中的初始化流程与此完全一致。tcp_accept函数设置connect_accept_callback回调函数。当已经监听的pcb与另一个主机建立连接关系后,该函数被调用。

回调函数中通过“xil_printf(“tcp_server: Connection Accepted\r\n”);”确认连接已建立,同时将tcp_client_connected置1,开始发送hello world。本程序中无需通过发送回调函数实现什么功能,因此没有注册该回调函数。
在这里插入图片描述
下载完程序后,打开网络调试助手选择TCP Client(否则检测不到开发板的IP地址),设置程序中绑定的IP地址和端口。连接后串口打印连接信息,开始发送hello world。

猜你喜欢

转载自blog.csdn.net/FPGADesigner/article/details/88776615