ZYNQ以太网通信之UDP(二)

免责声明:

本文所提供的信息和内容仅供参考。作者对本文内容的准确性、完整性、及时性或适用性不作任何明示或暗示的保证。在任何情况下,作者不对因使用本文内容而导致的任何直接或间接损失承担责任,包括但不限于数据丢失、业务中断或其他经济损失。

读者在使用本文信息时,应自行验证其准确性和适用性,并对其使用结果负责。本文内容不构成专业技术咨询或建议,具体的技术实现和应用应根据实际情况和需要进行详细分析和验证。

本文所涉及的任何商标、版权或其他知识产权均属于其各自的所有者。若本文中引用了第三方的资料或信息,引用仅为学术交流目的,不构成对第三方内容的认可或保证。

若有任何疑问或需进一步信息,请联系本文作者或相关专业人士。


前言

本期继续介绍LWIP-UDP 发送数据给目的端


一、初始化

这部分的代码无须更改,虽然很多冗余的,但方便调试,该程序的主要功能是初始化并配置一个基于 lwIP 的 UDP 客户端应用程序:

  1. 设置 MAC 地址:为开发板配置一个唯一的 MAC 地址。
  2. 初始化 lwIP 协议栈:调用 lwip_init() 初始化网络通讯。
  3. 添加网络接口:将网络接口添加到 lwIP 并设置为默认接口。
  4. 启用中断:启用网络通讯所需的系统中断。
  5. 配置 IP 地址:如果启用了 DHCP,程序会尝试动态获取 IP 地址;否则,使用默认的 IP 设置。
  6. 启动应用:调用 start_application() 启动具体的 UDP 客户端应用逻辑。

	struct netif *netif;

	/* the mac address of the board. this should be unique per board */
	unsigned char mac_ethernet_address[] = {
		0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };

	netif = &server_netif;

	init_platform();

	xil_printf("\r\n\r\n");
	xil_printf("-----lwIP RAW Mode UDP Client Application-----\r\n");

	/* initialize lwIP */
	lwip_init();

	/* Add network interface to the netif_list, and set it as default */
	if (!xemac_add(netif, NULL, NULL, NULL, mac_ethernet_address,
				PLATFORM_EMAC_BASEADDR)) {
		xil_printf("Error adding N/W interface\r\n");
		return -1;
	}
	netif_set_default(netif);

	/* now enable interrupts */
	platform_enable_interrupts();

	/* specify that the network if is up */
	netif_set_up(netif);

#if (LWIP_DHCP==1)
	/* Create a new DHCP client for this interface.
	 * Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
	 * the predefined regular intervals after starting the client.
	 */
	dhcp_start(netif);
	dhcp_timoutcntr = 24;
	while (((netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0))
		xemacif_input(netif);

	if (dhcp_timoutcntr <= 0) {
		if ((netif->ip_addr.addr) == 0) {
			xil_printf("ERROR: DHCP request timed out\r\n");
			assign_default_ip(&(netif->ip_addr),
					&(netif->netmask), &(netif->gw));
		}
	}

	/* print IP address, netmask and gateway */
#else
	assign_default_ip(&(netif->ip_addr), &(netif->netmask), &(netif->gw));
#endif
	print_ip_settings(&(netif->ip_addr), &(netif->netmask), &(netif->gw));

	xil_printf("\r\n");

	/* print app header */
	print_app_header();

二、UDP

绑定端口及IP
void start_application(void)
{
	err_t err;
	ip_addr_t remote_addr;
	u32_t i;

	err = inet_aton(UDP_SERVER_IP_ADDRESS, &remote_addr);
	if (!err) {
		xil_printf("Invalid Server IP address: %d\r\n", err);
		return;
	}

	for (i = 0; i < NUM_OF_PARALLEL_CLIENTS; i++) {
		/* Create Client PCB */
		pcb[i] = udp_new();
		if (!pcb[i]) {
			xil_printf("Error in PCB creation. out of memory\r\n");
			return;
		}

		err = udp_connect(pcb[i], &remote_addr, UDP_CONN_PORT);
		if (err != ERR_OK) {
			xil_printf("udp_client: Error on udp_connect: %d\r\n", err);
			udp_remove(pcb[i]);
			return;
		}
	}
	/* Wait for successful connection */
	usleep(10);
	reset_stats();

	/* initialize data buffer being sent with same as used in iperf */
	for (i = 0; i < UDP_SEND_BUFSIZE; i++)
		send_buf[i] = (i % 10) + '0';
}

udp_connect();绑定远端的IP(UDP_SERVER_IP_ADDRESS)及端口(UDP_CONN_PORT)

发送数据
void transfer_data(void)
{
	int i = 0;
	for (i = 0; i < NUM_OF_PARALLEL_CLIENTS; i++) {
		if (pcb[i] == NULL)
			return;
	}

	if (END_TIME || REPORT_INTERVAL_TIME) {
		u64_t now = get_time_ms();
		if (REPORT_INTERVAL_TIME) {
			if (client.i_report.start_time) {
				u64_t diff_ms = now - client.i_report.start_time;
				if (diff_ms >= REPORT_INTERVAL_TIME) {
					udp_conn_report(diff_ms, INTER_REPORT);
					client.i_report.start_time = 0;
					client.i_report.total_bytes = 0;
				}
			} else {
				client.i_report.start_time = now;
			}
		}

		if (END_TIME) {
			/* this session is time-limited */
			u64_t diff_ms = now - client.start_time;
			if (diff_ms >= END_TIME) {
				/* time specified is over,
				 * close the connection */
				udp_packet_send(FINISH);
				udp_conn_report(diff_ms, UDP_DONE_CLIENT);
				xil_printf("UDP test passed Successfully\n\r");
				return;
			}
		}
	}

	udp_packet_send(!FINISH);
}

transfer_data()中数据发送由udp_packet_send()负责,因此自接调用udp_packet_send()更省事。小编简化了该代码以专注于数据发送并减少代码量,去除多客户端支持、错误重试和终止逻辑,并简化包分配和发送流程。以下是一个精简版的代码示例:

static void udp_packet_send(void)
{
    int *payload;
    static int packet_id;
    struct pbuf *packet;

    /* 分配并填充数据包 */
    packet = pbuf_alloc(PBUF_TRANSPORT, UDP_SEND_BUFSIZE, PBUF_POOL);
    if (!packet) {
        xil_printf("Error allocating pbuf\r\n");
        return;
    }

    /* 将数据复制到数据包中 */
    pbuf_take(packet, send_buf, UDP_SEND_BUFSIZE);

    /* 设置包 ID */
    payload = (int*)(packet->payload);
    payload[0] = htonl(packet_id);

    /* 发送数据包 */
    udp_send(pcb[0], packet);

    /* 释放 pbuf 资源 */
    pbuf_free(packet);

    /* 包 ID 自增 */
    packet_id++;
}
使用方法

udp_packet_send 执行完一次后,更新send_buf,然后再执行udp_packet_send,一直循环这个过程即可


总结

以上就是本期讲解的全部内容。官方案例程序虽然繁琐,但便于调试。初始化过程无需修改程序,启用 DHCP 后会自动分配可用 IP,用户只需配置目标 IP 和端口号,然后将待发送的数据移动到 send_buf 即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值