uip UDP 服务器广播模式(客户端可以任意端口,并且主动向客户端发送数据)

目前移植uip,发现UDP 服务器模式下,必须指定本地端口以及客户端端口,否则只能讲客户端端口设置为0,才能接收任意端口的数据,但是无法发送数据,因为此时客户端端口设置为0了,我通过将原始数据包中的客户端端口保存下来,并且在发送的时候将客户端端口替换为指定的端口,发送完成之后又设置为0,这样就实现了向任意客户端端口发送数据.


uip.c

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.    if(uip_udp_conn->lport != 0 &&  
  2.       UDPBUF->destport == uip_udp_conn->lport &&  
  3.       (uip_udp_conn->rport == 0 ||  
  4.        UDPBUF->srcport == uip_udp_conn->rport) &&  
  5.       (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||  
  6. uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||  
  7. uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. (uip_udp_conn->rport == 0 ||  
  2.        UDPBUF->srcport == uip_udp_conn->rport) &&  
这句就限制了客户端端口为0或者指定端口


//udp_server.c

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************************************************* 
  2.  * 文件名:         udp_server.h 
  3.  * 功能:          uIP UDP服务器相关函数 
  4.  * 作者:          cp1300@139.com 
  5.  * 创建时间:        2014-06-04 
  6.  * 最后修改时间:  2014-06-04 
  7.  * 详细:          UDP服务器相关函数 
  8. *************************************************************************************************************/    
  9. #include "SYSTEM.h"  
  10. #include "tapdev.h"  
  11. #include "uip.h"  
  12. #include <string.h>  
  13. #include <stdio.h>      
  14. #include "uIP_user.h"  
  15. #include "udp_server.h"  
  16. #include "appconfig.h"  
  17.   
  18. u16 UDP_ServerPort = UDP_SERVER_PORT;           //UDP服务器本地端口,用于新数据端口识别  
  19. UIP_USER udp_server;                            //UDP 服务器数据结构  
  20. static bool isAnyPort = FALSE;                  //客户端任意端口标志  
  21.   
  22.   
  23.   
  24. /************************************************************************************************************************* 
  25. * 函数            :   void udp_server_connected(u16 ServerPort,u16 ClientPort) 
  26. * 功能            :   建立一个UDP服务器(广播方式) 
  27. * 参数            :   ServerPort:服务器本地端口,ClientPort:客户端端口,0:任意端口;非0:指定端口 
  28. * 返回            :   无 
  29. * 依赖            :   uip 
  30. * 作者            :   cp1300@139.com 
  31. * 时间            :   2014-06-04 
  32. * 最后修改时间    :   2014-06-05 
  33. * 说明            :   必须放在UDP客户端初始化之前 
  34. *************************************************************************************************************************/  
  35. void udp_server_connected(u16 ServerPort,u16 ClientPort)  
  36. {  
  37.     UDP_ServerPort = ServerPort;                            //本地端口  
  38.     uip_listen(HTONS(ServerPort));  
  39.     uip_udp_bind(&uip_udp_conns[0], htons(ServerPort));     //绑定本地端口  
  40.     udp_server.RxLen = 0;  
  41.     udp_server.TxLen = 0;  
  42.     udp_server.ServerPort = ServerPort;                     //服务器端口  
  43.     if(ClientPort != 0)                                     //指定端口  
  44.     {  
  45.         uip_udp_conns[0].rport = HTONS(ClientPort);  
  46.         udp_server.ClientPort = ClientPort;  
  47.         isAnyPort = FALSE;                                  //客户端指定端口  
  48.     }  
  49.     else  
  50.     {  
  51.         uip_udp_conns[0].rport = 0;  
  52.         isAnyPort = TRUE;                                   //客户端任意端口  
  53.     }  
  54. }  
  55.   
  56.   
  57.   
  58.   
  59. /************************************************************************************************************************* 
  60. * 函数            :   void udp_server_appcall(void) 
  61. * 功能            :   服务器回调函数,用于uip处理数据 
  62. * 参数            :   无 
  63. * 返回            :   无 
  64. * 依赖            :   uip 
  65. * 作者            :   cp1300@139.com 
  66. * 时间            :   2014-06-04 
  67. * 最后修改时间    :   2014-06-05 
  68. * 说明            :   无 
  69. *************************************************************************************************************************/  
  70. void udp_server_appcall(void)  
  71. {  
  72.       
  73.     if (uip_newdata())  
  74.     {  
  75.         if(uip_datalen() > UIP_RX_BUFF_ZISE) uip_len = UIP_RX_BUFF_ZISE; //限制大小  
  76.         memcpy(udp_server.RxBuff, uip_appdata, uip_len);                    //复制接收的数据到接收缓冲区  
  77.         udp_server.RxLen = uip_len;                                         //存储接收数据长度  
  78.         udp_server.ClientPort = (u16)(uip_buf[34]<<8) | uip_buf[35];      //强制获取客户端端口地址  
  79.         //uart_printf("%s\r\n",(char*)uip_appdata);  
  80.     }  
  81.     //新数据到达,轮询,发送数据   
  82.     if(uip_newdata() || uip_poll())  
  83.     {  
  84.         if(udp_server.TxLen)   
  85.         {  
  86.             uip_send(udp_server.TxBuff, udp_server.TxLen);  //发送UDP数据包  
  87.             udp_server.TxLen = 0;  
  88.         }  
  89.     }  
  90. }     
  91.   
  92.   
  93. /************************************************************************************************************************* 
  94. * 函数            :   void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort) 
  95. * 功能            :   UDP 服务器发送数据 
  96. * 参数            :   pBuff:发送数据缓冲区,len:发送数据长度,ClientPort:客户端端口 
  97. * 返回            :   无 
  98. * 依赖            :   uip 
  99. * 作者            :   cp1300@139.com 
  100. * 时间            :   2014-06-04 
  101. * 最后修改时间    :   2014-06-05 
  102. * 说明            :   无 
  103. *************************************************************************************************************************/  
  104. void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort)  
  105. {  
  106.     if(len > UIP_TX_BUFF_ZISE) len = UIP_TX_BUFF_ZISE;  
  107.     memcpy(udp_server.TxBuff, pBuff, len);  
  108.     udp_server.TxLen = len;  
  109.     uip_udp_conns[0].rport = HTONS(ClientPort);         //暂时将客户端端口设置为上一次发送数据的客户端端口  
  110. }  
  111.   
  112.   
  113.   
  114.   
  115. /************************************************************************************************************************* 
  116. * 函数            :   void udp_ServerSendEndCallBack(u16 conn) 
  117. * 功能            :   UDP发送数据完成回调函数,目前只支持一个服务器端口 
  118. * 参数            :   pBuff:发送数据缓冲区,len:发送数据长度,ClientPort:客户端端口 
  119. * 返回            :   无 
  120. * 依赖            :   uip 
  121. * 作者            :   cp1300@139.com 
  122. * 时间            :   2014-06-04 
  123. * 最后修改时间    :   2014-06-05 
  124. * 说明            :   由于UDP服务器的客户端IP设置为0后可以接收任意端口发来的数据,但是却无法发送数据 
  125.                     到0端口,因此在发送前将客户端端口设置为实际端口,发送完成后修改为0 
  126. *************************************************************************************************************************/  
  127. void udp_ServerSendEndCallBack(u16 conn)  
  128. {  
  129.     if((conn == 0) && (isAnyPort == TRUE))  
  130.     {  
  131.         uip_udp_conns[conn].rport = 0;      //将端口设置为0  
  132.     }  
  133. }  


//udp_server.h

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************************************************* 
  2.  * 文件名:         udp_server.h 
  3.  * 功能:          uIP UDP服务器相关函数 
  4.  * 作者:          cp1300@139.com 
  5.  * 创建时间:        2014-06-04 
  6.  * 最后修改时间:  2014-06-04 
  7.  * 详细:          UDP服务器相关函数 
  8. *************************************************************************************************************/    
  9. #ifndef _UDP_SERVER_H_  
  10. #define _UDP_SERVER_H_  
  11. #include "tcp.h"  
  12. #include "uip.h"  
  13. #include "system.h"  
  14. #include "uIP_user.h"  
  15.   
  16. extern UIP_USER udp_server; //UDP 服务器数据结构  
  17. extern u16 UDP_ServerPort;  //UDP服务器本地端口  
  18.   
  19.   
  20. void udp_server_connected(u16 ServerPort,u16 ClientPort);               //建立一个UDP服务器(广播方式)  
  21. void udp_server_appcall(void);                                          //服务器回调函数,用于uip处理数据  
  22. void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort);      //UDP 服务器发送数据  
  23. void udp_ServerSendEndCallBack(u16 conn);                               //UDP发送数据完成回调函数  
  24.   
  25.   
  26.   
  27.   
  28. #endif //_UDP_SERVER_H_  


//结构体定义

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //用户连接数据结构  
  2. #define UIP_RX_BUFF_ZISE    512     //接收数据缓冲区大小  
  3. #define UIP_TX_BUFF_ZISE    512     //发送数据缓冲区大小  
  4. typedef struct  
  5. {  
  6.     u16 RxLen;      //接收数据长度  
  7.     u16 TxLen;      //发送数据长度  
  8.     u16 ClientPort; //客户端端口  
  9.     u16 ServerPort; //服务器端口  
  10.     u8  RxBuff[UIP_RX_BUFF_ZISE];   //接收缓冲区  
  11.     u8  TxBuff[UIP_TX_BUFF_ZISE];   //接收缓冲区  
  12. }UIP_USER;  

//配置定义

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #define DHCP_TIME_OUT               60                  //DHCP获取超时时间,单位S  
  2. #define TCP_LINK_SERVER_TIME_OUT    10                  //连接服务器超时时间,单位S  
  3. #define TCP_LINK_SERVER_CNT         5                   //连接服务器重试次数  
  4. #define TCP_CLIENT_PORT_AUTO        1                   //客户端端口随机分配  
  5. #define TCP_CLIENT_DEFAULT_PORT     2400                //客户端默认端口  
  6. #define TCP_SERVER_DEFAULT_IP       192,168,16,104      //服务器默认IP地址  
  7. #define TCP_SERVER_DEFAULT_PORT     8888                //服务器默认端口  
  8. #define TCP_SEND_TIME_OUT           5                   //数据发送超时时间,单位S  
  9.   
  10. #define UDP_LOCAL_PORT              8000                //UDP连接本地端口  
  11. #define UDP_REMOTE_PORT             8899                //UDP连接远程端口  
  12. #define UDP_SERVER_PORT             8100                //UDP服务器本地端口  

//数据端口调度

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //UDP应用接口函数(UIP_UDP_APPCALL)  
  2. void udp_appcall(void)  
  3. {     
  4.   
  5.     switch(uip_udp_conn->lport)//本地监听端口  
  6.     {  
  7.         //用于DHCP  
  8.         case HTONS(67): dhcpc_appcall();break;  
  9.         case HTONS(68):  dhcpc_appcall();break;  
  10.         default:   
  11.         {  
  12.             if(uip_udp_conn->lport == HTONS(UDP_ClinetPort))     //UDP客户端  
  13.             {  
  14.                 udp_client_appcall();  
  15.             }  
  16.             else if(uip_udp_conn->lport == HTONS(UDP_ServerPort))    //UDP服务器  
  17.             {  
  18.                 udp_server_appcall();  
  19.             }  
  20.         }break;  
  21.     }               
  22. }  

//UDP调度处理,必须在数据发送完成后调用自定义的回调函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for(i = 0; i < UIP_UDP_CONNS; i++)  
  2. {  
  3.     //只处理发送事件  
  4.     uip_udp_periodic(i);    //处理UDP通信事件  
  5.     //当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0  
  6.     //需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)  
  7.     if(uip_len > 0)  
  8.     {  
  9.         LED2 = ~ LED2;  
  10.         uip_arp_out();//加以太网头结构,在主动连接时可能要构造ARP请求  
  11.         tapdev_send();//发送数据到以太网  
  12.         udp_ServerSendEndCallBack(i);   //数据发送完成后一定要调用回调函数  
  13.         break;  
  14.     }  
  15. }  
调用这个实现将客户端端口设置为0,这样就可以接受来自任意端口的数据
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. udp_ServerSendEndCallBack(i);   //数据发送完成后一定要调用回调函数  




//初始化并处理UDP服务器数据

//实现收到后立即返回数据

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. udp_server_connected(UDP_SERVER_PORT, 0);   //新建UDP服务器,客户端任意端口  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //UDP服务器数据处理  
  2.         if(udp_server.RxLen > 0)  
  3.         {  
  4.               
  5.             uart_printf("服务器端口:%d\r\n",udp_server.ServerPort);  
  6.             uart_printf("客户端端口:%d\r\n",udp_server.ClientPort);  
  7.             uart_printf("UDP Server Rx(%dB):%s\r\n",udp_server.RxLen,(char*)udp_server.RxBuff);  
  8.             udp_ServerSendDataPackage(udp_server.RxBuff, udp_server.RxLen, udp_server.ClientPort);  
  9.             udp_server.RxLen = 0;  
  10.         }  


//仿真结果


posted @ 2016-08-08 12:54  SuperThinker  阅读(47)  评论(0编辑  收藏  举报  来源