uip UDP 服务器广播模式(客户端可以任意端口,并且主动向客户端发送数据)
目前移植uip,发现UDP 服务器模式下,必须指定本地端口以及客户端端口,否则只能讲客户端端口设置为0,才能接收任意端口的数据,但是无法发送数据,因为此时客户端端口设置为0了,我通过将原始数据包中的客户端端口保存下来,并且在发送的时候将客户端端口替换为指定的端口,发送完成之后又设置为0,这样就实现了向任意客户端端口发送数据.
uip.c
- if(uip_udp_conn->lport != 0 &&
- UDPBUF->destport == uip_udp_conn->lport &&
- (uip_udp_conn->rport == 0 ||
- UDPBUF->srcport == uip_udp_conn->rport) &&
- (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
- uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
- uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
- (uip_udp_conn->rport == 0 ||
- UDPBUF->srcport == uip_udp_conn->rport) &&
//udp_server.c
- /*************************************************************************************************************
- * 文件名: udp_server.h
- * 功能: uIP UDP服务器相关函数
- * 作者: cp1300@139.com
- * 创建时间: 2014-06-04
- * 最后修改时间: 2014-06-04
- * 详细: UDP服务器相关函数
- *************************************************************************************************************/
- #include "SYSTEM.h"
- #include "tapdev.h"
- #include "uip.h"
- #include <string.h>
- #include <stdio.h>
- #include "uIP_user.h"
- #include "udp_server.h"
- #include "appconfig.h"
- u16 UDP_ServerPort = UDP_SERVER_PORT; //UDP服务器本地端口,用于新数据端口识别
- UIP_USER udp_server; //UDP 服务器数据结构
- static bool isAnyPort = FALSE; //客户端任意端口标志
- /*************************************************************************************************************************
- * 函数 : void udp_server_connected(u16 ServerPort,u16 ClientPort)
- * 功能 : 建立一个UDP服务器(广播方式)
- * 参数 : ServerPort:服务器本地端口,ClientPort:客户端端口,0:任意端口;非0:指定端口
- * 返回 : 无
- * 依赖 : uip
- * 作者 : cp1300@139.com
- * 时间 : 2014-06-04
- * 最后修改时间 : 2014-06-05
- * 说明 : 必须放在UDP客户端初始化之前
- *************************************************************************************************************************/
- void udp_server_connected(u16 ServerPort,u16 ClientPort)
- {
- UDP_ServerPort = ServerPort; //本地端口
- uip_listen(HTONS(ServerPort));
- uip_udp_bind(&uip_udp_conns[0], htons(ServerPort)); //绑定本地端口
- udp_server.RxLen = 0;
- udp_server.TxLen = 0;
- udp_server.ServerPort = ServerPort; //服务器端口
- if(ClientPort != 0) //指定端口
- {
- uip_udp_conns[0].rport = HTONS(ClientPort);
- udp_server.ClientPort = ClientPort;
- isAnyPort = FALSE; //客户端指定端口
- }
- else
- {
- uip_udp_conns[0].rport = 0;
- isAnyPort = TRUE; //客户端任意端口
- }
- }
- /*************************************************************************************************************************
- * 函数 : void udp_server_appcall(void)
- * 功能 : 服务器回调函数,用于uip处理数据
- * 参数 : 无
- * 返回 : 无
- * 依赖 : uip
- * 作者 : cp1300@139.com
- * 时间 : 2014-06-04
- * 最后修改时间 : 2014-06-05
- * 说明 : 无
- *************************************************************************************************************************/
- void udp_server_appcall(void)
- {
- if (uip_newdata())
- {
- if(uip_datalen() > UIP_RX_BUFF_ZISE) uip_len = UIP_RX_BUFF_ZISE; //限制大小
- memcpy(udp_server.RxBuff, uip_appdata, uip_len); //复制接收的数据到接收缓冲区
- udp_server.RxLen = uip_len; //存储接收数据长度
- udp_server.ClientPort = (u16)(uip_buf[34]<<8) | uip_buf[35]; //强制获取客户端端口地址
- //uart_printf("%s\r\n",(char*)uip_appdata);
- }
- //新数据到达,轮询,发送数据
- if(uip_newdata() || uip_poll())
- {
- if(udp_server.TxLen)
- {
- uip_send(udp_server.TxBuff, udp_server.TxLen); //发送UDP数据包
- udp_server.TxLen = 0;
- }
- }
- }
- /*************************************************************************************************************************
- * 函数 : void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort)
- * 功能 : UDP 服务器发送数据
- * 参数 : pBuff:发送数据缓冲区,len:发送数据长度,ClientPort:客户端端口
- * 返回 : 无
- * 依赖 : uip
- * 作者 : cp1300@139.com
- * 时间 : 2014-06-04
- * 最后修改时间 : 2014-06-05
- * 说明 : 无
- *************************************************************************************************************************/
- void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort)
- {
- if(len > UIP_TX_BUFF_ZISE) len = UIP_TX_BUFF_ZISE;
- memcpy(udp_server.TxBuff, pBuff, len);
- udp_server.TxLen = len;
- uip_udp_conns[0].rport = HTONS(ClientPort); //暂时将客户端端口设置为上一次发送数据的客户端端口
- }
- /*************************************************************************************************************************
- * 函数 : void udp_ServerSendEndCallBack(u16 conn)
- * 功能 : UDP发送数据完成回调函数,目前只支持一个服务器端口
- * 参数 : pBuff:发送数据缓冲区,len:发送数据长度,ClientPort:客户端端口
- * 返回 : 无
- * 依赖 : uip
- * 作者 : cp1300@139.com
- * 时间 : 2014-06-04
- * 最后修改时间 : 2014-06-05
- * 说明 : 由于UDP服务器的客户端IP设置为0后可以接收任意端口发来的数据,但是却无法发送数据
- 到0端口,因此在发送前将客户端端口设置为实际端口,发送完成后修改为0
- *************************************************************************************************************************/
- void udp_ServerSendEndCallBack(u16 conn)
- {
- if((conn == 0) && (isAnyPort == TRUE))
- {
- uip_udp_conns[conn].rport = 0; //将端口设置为0
- }
- }
//udp_server.h
- /*************************************************************************************************************
- * 文件名: udp_server.h
- * 功能: uIP UDP服务器相关函数
- * 作者: cp1300@139.com
- * 创建时间: 2014-06-04
- * 最后修改时间: 2014-06-04
- * 详细: UDP服务器相关函数
- *************************************************************************************************************/
- #ifndef _UDP_SERVER_H_
- #define _UDP_SERVER_H_
- #include "tcp.h"
- #include "uip.h"
- #include "system.h"
- #include "uIP_user.h"
- extern UIP_USER udp_server; //UDP 服务器数据结构
- extern u16 UDP_ServerPort; //UDP服务器本地端口
- void udp_server_connected(u16 ServerPort,u16 ClientPort); //建立一个UDP服务器(广播方式)
- void udp_server_appcall(void); //服务器回调函数,用于uip处理数据
- void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort); //UDP 服务器发送数据
- void udp_ServerSendEndCallBack(u16 conn); //UDP发送数据完成回调函数
- #endif //_UDP_SERVER_H_
//结构体定义
- //用户连接数据结构
- #define UIP_RX_BUFF_ZISE 512 //接收数据缓冲区大小
- #define UIP_TX_BUFF_ZISE 512 //发送数据缓冲区大小
- typedef struct
- {
- u16 RxLen; //接收数据长度
- u16 TxLen; //发送数据长度
- u16 ClientPort; //客户端端口
- u16 ServerPort; //服务器端口
- u8 RxBuff[UIP_RX_BUFF_ZISE]; //接收缓冲区
- u8 TxBuff[UIP_TX_BUFF_ZISE]; //接收缓冲区
- }UIP_USER;
//配置定义
- #define DHCP_TIME_OUT 60 //DHCP获取超时时间,单位S
- #define TCP_LINK_SERVER_TIME_OUT 10 //连接服务器超时时间,单位S
- #define TCP_LINK_SERVER_CNT 5 //连接服务器重试次数
- #define TCP_CLIENT_PORT_AUTO 1 //客户端端口随机分配
- #define TCP_CLIENT_DEFAULT_PORT 2400 //客户端默认端口
- #define TCP_SERVER_DEFAULT_IP 192,168,16,104 //服务器默认IP地址
- #define TCP_SERVER_DEFAULT_PORT 8888 //服务器默认端口
- #define TCP_SEND_TIME_OUT 5 //数据发送超时时间,单位S
- #define UDP_LOCAL_PORT 8000 //UDP连接本地端口
- #define UDP_REMOTE_PORT 8899 //UDP连接远程端口
- #define UDP_SERVER_PORT 8100 //UDP服务器本地端口
//数据端口调度
- //UDP应用接口函数(UIP_UDP_APPCALL)
- void udp_appcall(void)
- {
- switch(uip_udp_conn->lport)//本地监听端口
- {
- //用于DHCP
- case HTONS(67): dhcpc_appcall();break;
- case HTONS(68): dhcpc_appcall();break;
- default:
- {
- if(uip_udp_conn->lport == HTONS(UDP_ClinetPort)) //UDP客户端
- {
- udp_client_appcall();
- }
- else if(uip_udp_conn->lport == HTONS(UDP_ServerPort)) //UDP服务器
- {
- udp_server_appcall();
- }
- }break;
- }
- }
//UDP调度处理,必须在数据发送完成后调用自定义的回调函数
- for(i = 0; i < UIP_UDP_CONNS; i++)
- {
- //只处理发送事件
- uip_udp_periodic(i); //处理UDP通信事件
- //当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0
- //需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)
- if(uip_len > 0)
- {
- LED2 = ~ LED2;
- uip_arp_out();//加以太网头结构,在主动连接时可能要构造ARP请求
- tapdev_send();//发送数据到以太网
- udp_ServerSendEndCallBack(i); //数据发送完成后一定要调用回调函数
- break;
- }
- }
- udp_ServerSendEndCallBack(i); //数据发送完成后一定要调用回调函数
//初始化并处理UDP服务器数据
//实现收到后立即返回数据
- udp_server_connected(UDP_SERVER_PORT, 0); //新建UDP服务器,客户端任意端口
- //UDP服务器数据处理
- if(udp_server.RxLen > 0)
- {
- uart_printf("服务器端口:%d\r\n",udp_server.ServerPort);
- uart_printf("客户端端口:%d\r\n",udp_server.ClientPort);
- uart_printf("UDP Server Rx(%dB):%s\r\n",udp_server.RxLen,(char*)udp_server.RxBuff);
- udp_ServerSendDataPackage(udp_server.RxBuff, udp_server.RxLen, udp_server.ClientPort);
- udp_server.RxLen = 0;
- }