第二十一章 UDP21.1 UDP例程概述 UDP例程可以让W7500EVB实现UDP协议,进行非连接,快速的数据传输。但UDP协议传输数据本身是不稳定的,不会建立连接也不会检查应答,所以可能会造成丢包,但同时由于数据传输过程不需要进行连接过程,也不需要判断响应等,所以其传输速度比TCP协议会快很多。 21.2 UDP协议简介UDP协议是英文UserDatagramProtocol的缩写,即用户数据报协议,主要用来支持那些需要在计算机之间传输数据的网络应用。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。在网络中它与TCP协议一样,处于TCP/IP协议体系中的传输层,处于IP协议的上一层,用于处理数据包。与TCP不同的是,UDP是一种无连接的协议。也就是说,UDP发送数据之前不需要先建立连接(当然发送数据结束时也没必要释放连接),因此减少了时间上的开销。同时,UDP不使用拥塞控制,也不保证可靠交付,因此主机不需要维持具有许多参数的、复杂的连接状态表。总体来说,UDP是一种不可靠的数据传输协议,能提供比较快速的数据传输速度,但是并不保证数据的正确性。这些特性与TCP刚好相反。 UDP协议支持单播、广播和多播(组播)的通信。 网络之间的节点就好像人们在通话一样,如果一个人跟另外一个人说话,那么就可以称作是“单播”,单播是“一对一”通信,一次只能将数据传输给一个目的地址。网络上绝大部分的数据是以单播形式传输的,比如收发电子邮件、浏览网页。 广播通信则可理解为,一个人通过广播喇叭对在场所有人讲话,是“一对多”,信息一下子就散播开来。广播通信使用广播地址(255.255.255.255),将数据发送给所有的可接收的目的地址。 多播,又叫组播。与广播不同,它是把信息同时传递给一组目的地址,即与多个、在多播组注册的目的地址进行通信。 但广播和多播仅应用于UDP,它们对需将报文同时传往多个接收者的应用来说十分重要。在某些情况下,UDP协议可能会变得非常有用。因为UDP具有TCP所望尘莫及的速度优势。虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,严重影响速度。反观UDP,由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证;在给定的主机上能识别多个目的地址,同时允许多个应用程序在同一台主机上工作,并能独立地进行数据报的发送和接收,包括视频会议、网络电话在内的众多网络应用都需要使用UDP。基于UDP的应用层协议有:TFTP、SNMP、NFS、DNS、BOOTP。 21.3 UDP数据报格式采用UDP的端口来标识,首先UDP端口号可以是固定的,发送方只需要发送数据到指定端口即可。对于不同功能可以分配不同的端口号,来区分不同功能的数据。对于标准功能,也可以预先分配端口号,实现该功能的程序可以申请该端口号,这样,就可以将数据包发往申请的端口来实现此功能。 图21.3.1UDP报文组成结构 UDP源端端口和目的地端口指定了2个16bit的端口号。源端端口号可选,如果指定了,则相应数据包发往该端口,如果没有指定,则设为0。 UDP用户包长度表示了整个UDP数据包的8bit字节数据的数量,包含头部和数据部分,最小为8(数据可以为0)。 UDP校验和用以保证UDP数据包的完整性。该字段可选,没有计算校验和的UDP数据包应该将该字段设为0。 20.4 UDP例程解析 例程初始化部分就不再赘述,有需要的可以查看Network install例程中初始化部分的讲解。下面我们具体分析UDP应用函数。 - 1. int32_t udps(uint8_t sn, uint8_t* buf, uint16_t port)
- 2. {
- 3. uint16_t size;
- 4.
- 5. switch(getSn_SR(sn)) /*获取socket的状态*/
- 6. {
- 7. case SOCK_UDP : /*socket初始化完成*/
- 8. if((size = getSn_RX_RSR(sn)) > 0)
- 9. {
- 10. if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
- 11. ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);/*W7500接收计算机发送来的数据*/
- 12. printf("%s\r\n",buf);
- 13. if(ret <= 0)
- 14. {
- 15. #ifdef _LOOPBACK_DEBUG_
- 16. printf("%d: recvfrom error. %ld\r\n",sn,ret);
- 17. #endif
- 18. return ret;
- 19. }
- 20. size = (uint16_t) ret;
- 21. sentsize = 0;
- 22. while(sentsize != size)
- 23. {
- 24. ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);/*W7500把接收到的数据发送给Remote*/
- 25. if(ret < 0)
- 26. {
- 27. #ifdef _LOOPBACK_DEBUG_
- 28. printf("%d: sendto error. %ld\r\n",sn,ret);
- 29. #endif
- 30. return ret;
- 31. }
- 32. sentsize += ret;
- 33. }
- 34. }
- 35. break;
- 36. case SOCK_CLOSED: /*socket处于关闭状态*/
- 37. if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn) /*初始化socket*/
- 38. return ret;
- 39. #ifdef _LOOPBACK_DEBUG_
- 40. printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, port);
- 41. #endif
- 42. break;
- 43. default :
- 44. break;
- 45. }
- 46. return 1;
- 47. }
复制代码
SOCK_UDP 的状态,默认是关闭,37行初始化SOCK_UDP。之后8行则是判断是否有数据发送到数据缓冲区,11行判断如果有就将数据复制到buf数组内,然后打印串口信息,并且将数据回发到发送方。 至此,UDP例程代码解析就结束了。将UDP例程编译烧录后打印串口信息结果如图20.4.1。 图20.4.1UDP例程打印结果 使用网络调试助手,测试PC和W7500EVB,是否能收发数据。结果如图20.4.2,连接成功,收发数据正常。W7500EVB设置为UDP协议成功。 图20.4.2 UDP数据交互
|