在uboot中使用UDP协议实现UDP通信

原创 2015年11月20日 16:55:38

本文所讲的uboot是基于海思芯片的uboot(如HI3520D)。因为TFTP协议是基于UDP协议,所以本文大部分代码是直接使用TFTP的。在写代码之前复习一下TFTP报文和UDP报文的结构。


每行占64位(bit),共8字节(byte)。

UDP报文:太网包头+IP包头+UDP包头+数据

TFTP报文:太网包头+IP包头+UDP包头+TFTP包头+数据

填充太网包头+IP包头+UDP包头的话直接调用TFTP报文的就可以了。


步骤:

一、像TFTP命令一样写一个UDP命令

我直接在cmd_net.c中添加如下代码(当然也可以新建一个cmd_udp.c,那样的话要在u-boot-2010.06/include/configs/hi3520d.h文件里面添加

#define CONFIG_CMD_UDP,,并且在common目录的Makefile里面添加COBJS-$(CONFIG_CMD_UDP) += cmd_udp.o):


在下面实现netboot_UDP_TCP 函数,记得定义一下这个函数。

static int netboot_UDP_TCP (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[])
{
	extern ulong upload_addr;
	extern ulong upload_size;
	char *s;
	char *end;
	int   rcode = 0;
	int   size;
	ulong addr;

	/* pre-set load_addr */
	if ((s = getenv("loadaddr")) != NULL) {
		load_addr = simple_strtoul(s, NULL, 16);
	}

	switch (argc) {
	case 1:
		break;
	case 2:	
		pkt_data = argv[1]; 
		break;
	default: cmd_usage(cmdtp);
		show_boot_progress (-80);
		return 1;
	}
	show_boot_progress (80);
	if ((size = NetLoop(proto)) < 0) {
		show_boot_progress (-81);
		return 1;
	}
	show_boot_progress (81);
	/* NetLoop ok, update environment */
	netboot_update_env();

	/* done if no file was loaded (no errors though) */
	if (size == 0) {
		show_boot_progress (-82);
		return 0;
	}
	/* Loading ok, check if we should attempt an auto-start */
	if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
		char *local_args[2];
		local_args[0] = argv[0];
		local_args[1] = NULL;

		printf ("Automatic boot of image at addr 0x%08lX ...\n",
			load_addr);
		show_boot_progress (82);
		rcode = do_bootm (cmdtp, 0, 1, local_args);
	}

	if (rcode < 0)
		show_boot_progress (-83);
	else
		show_boot_progress (84);
	return rcode;
}


二、为了清楚一点我在net目录下touch一个udp.c和udp.h文件

第一步之后会跳到net目录下的net.c的NetLoop函数,但是在switch(protocol)里面添加

case UDP:

UdpStart();

break;

UDP协议在net.h里面添加


Udpstart函数在udp.c里面实现,所以接下来会跳到net目录下的udp.c文件里面,udp.c和udp.h代码如下:

udp.c(主要是发送已经填充好的报文,这里发送函数直接调用TFTP协议使用的发送函数):

#include <common.h>
#include <command.h>
#include <net.h>
#include "tftp.h"
#include "bootp.h"
#include "udp.h"

#define TIMEOUT	 	1000		/* Seconds to timeout for a lost pkt	*/
#ifndef	CONFIG_NET_RETRY_COUNT
# define TIMEOUT_COUNT	10		/* # of timeouts before giving up  */
#else
# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 2)
#endif

static ulong UdpTimeoutMSecs = TIMEOUT;
static int UdpTimeoutCountMax = TIMEOUT_COUNT;

/*
 * These globals govern the timeout behavior when attempting a connection to a
 * TFTP server. UdpRRQTimeoutMSecs specifies the number of milliseconds to
 * wait for the server to respond to initial connection. Second global,
 * UdpRRQTimeoutCountMax, gives the number of such connection retries.
 * UdpRRQTimeoutCountMax must be non-negative and UdpRRQTimeoutMSecs must be
 * positive. The globals are meant to be set (and restored) by code needing
 * non-standard timeout behavior when initiating a TFTP transfer.
 */
ulong UdpRRQTimeoutMSecs = TIMEOUT;
int UdpRRQTimeoutCountMax = TIMEOUT_COUNT;

static IPaddr_t UdpServerIP;
static int	UdpServerPort;		/* The UDP port at their end		*/
static int	UdpOurPort;		/* The UDP port at our end		*/
static int	UdpTimeoutCount;		

static void UdpSend (void);
static void UdpTimeout (void);

/**********************************************************************/

static void
UdpSend (void)
{
	volatile uchar *	pkt;
	volatile uchar *	xp;
	int			len = 0;
	int			uplen=0;
	volatile ushort *s;


	/*
	 *	We will always be sending some sort of packet, so
	 *	cobble together the packet headers now.
	 */
	pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
	len = strlen(pkt_data);
	memcpy(pkt, pkt_data, len);
	printf("pkt_data=%s,len=%d\n", pkt_data,len);
	NetSendUDPPacket(NetServerEther, UdpServerIP, UdpServerPort, UdpOurPort, len);
}


static void
UdpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	ushort proto;
	ushort *s;
	int i;
	printf("receive udp packet\n");
	s = (uchar *)pkt;
	printf("len=%d\n",len);
	printf("%.*s\n", len, s);
	
}


static void
UdpTimeout (void)
{
	if (++UdpTimeoutCount > UdpTimeoutCountMax) {
		puts ("\nRetry count exceeded; starting again\n");
		NetStartAgain ();
	} else {
		puts ("T ");
		NetSetTimeout (UdpTimeoutMSecs * CFG_HZ, UdpTimeout);
		UdpSend ();
	}
}


void
UdpStart (void)
{
	char *ep;             /* Environment pointer */

	/*
	 * Allow the user to choose UDP blocksize and timeout.
	 * UDP protocol has a minimal timeout of 1 second.
	 */

	if ((ep = getenv("udptimeout")) != NULL)
		UdpTimeoutMSecs = simple_strtol(ep, NULL, 10);

	if (UdpTimeoutMSecs < 1000) {
		printf("UDP timeout (%ld ms) too low, "
			"set minimum = 1000 ms\n",
			UdpTimeoutMSecs);
		UdpTimeoutMSecs = 1000;
	}

	UdpServerIP = NetServerIP;
	
#if defined(CONFIG_NET_MULTI)
	printf ("Using %s device\n", eth_get_name());
#endif		
	UdpTimeoutCountMax = UdpRRQTimeoutCountMax;

	NetSetTimeout (UdpTimeoutMSecs * CFG_HZ, UdpTimeout);
	NetSetHandler (UdpHandler);

	UdpServerPort = 75;//WELL_KNOWN_PORT;
	UdpTimeoutCount = 0;
	UdpOurPort = 1024;
	UdpPktLen = 0;

	/* zero out server ether in case the server ip has changed */
	memset(NetServerEther, 0, 6);

	UdpSend ();


udp.h

#ifndef __UDP_H__
#define __UDP_H__

extern void UdpStart (void);

#endif


三、代码基本实现完了,最后是测试

在这里千万别像TFTP命令一样用69端口和TFTP服务器测试UDP协议。否则Wireshark抓到的包是TFTP协议的包,因为TFTP服务器把收到的UDP包当成是TFTP包了,并且TFTP包都会有一个操作选项(已经定义好的),所以抓到是unknown的包。

这里最好是使用能接收UDP包的工具当服务器,比如在绿软家园里面下载的YAT、TCP&UDP测试工具 V1.02等等。这次测试使用的是YAT,打开YAT并设置uboot的IP、端口号1024、服务器端口号75


现在在uboot中开始发包,数据为字符串:funanfengfunanfengfunanfeng

Wireshark抓到的包:


YAT服务器端收到的数据:



现在测试在uboot里面接收服务器发过来的数据:

从服务器向uboot发一个字符串:abcdefgabcdefg


Wireshark抓到的包:



在uboot中收到接收到服务器发过来的字符串,但是不知为什么发完数据包之后还发过来一个空包,在其他的测试工具就没这种现象,有待解决。


版权声明:本文为博主原创文章,未经博主允许不得转载。

QQ--基于TCP/UDP协议的通讯原理

QQ是一个基于TCP/UDP协议的通讯软件    www.2cto.com   发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服 务器,只不过不是常用的那些,那...
  • smartsmile2012
  • smartsmile2012
  • 2016年06月07日 20:31
  • 1800

UDP协议的用途

目前我们用的大多数应用层的协议都是基于TCP的,例如:telent, ftp, http, https, smtp.很少有基于UDPy协议的应用层的协议。     那么UDP协议到底有什么作用呢? ...
  • xixihaha331
  • xixihaha331
  • 2016年04月08日 17:21
  • 615

Java简单的UDP通讯例子

内容:简单的UDP通讯例子。 Receiver: public class Receiver { public static void main(String[] args) { D...
  • u011345136
  • u011345136
  • 2015年05月19日 11:32
  • 2611

c++中UDP通信实现

client端 #include #include #pragma comment(lib,"ws2_32.lib") void main()  {  WORD wVersionRequ...
  • cherish_2012
  • cherish_2012
  • 2014年12月05日 09:06
  • 16245

C语言实现UDP连接的参考代码

C语言实现UDP连接的参考代码,Client连接上Server后将自己所在目录下的"liu"文件中的前三行文字发送到Server端去,然后Server负责接收和显示。 /**************...
  • zgrjkflmkyc
  • zgrjkflmkyc
  • 2013年02月23日 15:13
  • 10696

Android Socket通信(一)--基于UDP协议通信

最近做功能需要用到使用UDP协议和服务器进行通信,之前没有接触这一块,所以花了些时间了解和实现,这里做一下记录和分享。...
  • lizebin_bin
  • lizebin_bin
  • 2017年03月16日 15:03
  • 2175

UDP协议点对点(P2P)通讯(或者说NAT穿越)实例

UDP协议点对点(P2P)通讯实例。 【实验环境】 一个服务端Server,两个客户端:Client1和Client2 。Server和Client1在Linux系统上运行,Client2在Win...
  • iw1210
  • iw1210
  • 2016年07月24日 11:41
  • 2076

基于udp的socket编程小例子之使用多线程进行通信

package udpDemo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr...
  • leixingbang1989
  • leixingbang1989
  • 2015年10月28日 16:52
  • 1178

TCP&UDP测试工具 创建UDP通信设置教程

使用TCP&UDP测试工具软件以UDP的通信方式发送一组数据,然后在TCP&UDP测试工具的接收区接收显示发送的数据。 需要使用路由器创建一个虚拟服务器,这样这个测试能在一台电脑上完成。 虚拟服务器 ...
  • hhhhh89
  • hhhhh89
  • 2016年10月14日 21:52
  • 7350

python实现UDP通信

UDP,用户数据报传输协议,它位于TCP/IP协议的传输层,是一种无连接的协议,它发送的报文不能确定是否完整地到达了另外一端。UDP广泛应用于需要相互传输数据的网络应用中,如QQ使用的就是UDP协议。...
  • u011608357
  • u011608357
  • 2014年02月23日 23:25
  • 4894
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在uboot中使用UDP协议实现UDP通信
举报原因:
原因补充:

(最多只允许输入30个字)