uip UDP server广播模式(client能够随意port,而且主动向client发送数据)
眼下移植uip,发现UDP server模式下,必须指定本地port以及clientport,否则仅仅能讲clientport设置为0,才干接收随意port的数据,可是无法发送数据,由于此时clientport设置为0了,我通过将原始数据包中的clientport保存下来,而且在发送的时候将clientport替换为指定的port,发送完毕之后又设置为0,这样就实现了向随意clientport发送数据.
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) &&这句就限制了client端口为0或者指定端口
//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服务器本地port,用于新数据port识别 UIP_USER udp_server; //UDP 服务器数据结构 static bool isAnyPort = FALSE; //client随意port标志 /************************************************************************************************************************* * 函数 : void udp_server_connected(u16 ServerPort,u16 ClientPort) * 功能 : 建立一个UDP服务器(广播方式) * 參数 : ServerPort:服务器本地port,ClientPort:clientport,0:随意port;非0:指定port * 返回 : 无 * 依赖 : uip * 作者 : cp1300@139.com * 时间 : 2014-06-04 * 最后改动时间 : 2014-06-05 * 说明 : 必须放在UDPclient初始化之前 *************************************************************************************************************************/ void udp_server_connected(u16 ServerPort,u16 ClientPort) { UDP_ServerPort = ServerPort; //本地port uip_listen(HTONS(ServerPort)); uip_udp_bind(&uip_udp_conns[0], htons(ServerPort)); //绑定本地port udp_server.RxLen = 0; udp_server.TxLen = 0; udp_server.ServerPort = ServerPort; //服务器port if(ClientPort != 0) //指定port { uip_udp_conns[0].rport = HTONS(ClientPort); udp_server.ClientPort = ClientPort; isAnyPort = FALSE; //client指定port } else { uip_udp_conns[0].rport = 0; isAnyPort = TRUE; //client随意port } } /************************************************************************************************************************* * 函数 : 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]; //强制获取clientport地址 //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: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); //临时将clientport设置为上一次发送数据的clientport } /************************************************************************************************************************* * 函数 : void udp_ServerSendEndCallBack(u16 conn) * 功能 : UDP发送数据完毕回调函数,眼下仅仅支持一个服务器port * 參数 : pBuff:发送数据缓冲区,len:发送数据长度,ClientPort:clientport * 返回 : 无 * 依赖 : uip * 作者 : cp1300@139.com * 时间 : 2014-06-04 * 最后改动时间 : 2014-06-05 * 说明 : 因为UDP服务器的clientIP设置为0后能够接收随意port发来的数据,可是却无法发送数据 到0port,因此在发送前将clientport设置为实际port,发送完毕后改动为0 *************************************************************************************************************************/ void udp_ServerSendEndCallBack(u16 conn) { if((conn == 0) && (isAnyPort == TRUE)) { uip_udp_conns[conn].rport = 0; //将port设置为0 } }
//udp_server.h
/************************************************************************************************************* * 文件名称: udp_server.h * 功能: uIP UDPserver相关函数 * 作者: cp1300@139.com * 创建时间: 2014-06-04 * 最后改动时间: 2014-06-04 * 具体: UDPserver相关函数 *************************************************************************************************************/ #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 server数据结构 extern u16 UDP_ServerPort; //UDPserver本地port void udp_server_connected(u16 ServerPort,u16 ClientPort); //建立一个UDPserver(广播方式) void udp_server_appcall(void); //server回调函数,用于uip处理数据 void udp_ServerSendDataPackage(u8 *pBuff, u16 len,u16 ClientPort); //UDP server发送数据 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; //clientport u16 ServerPort; //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 //连接server超时时间,单位S #define TCP_LINK_SERVER_CNT 5 //连接server重试次数 #define TCP_CLIENT_PORT_AUTO 1 //clientport随机分配 #define TCP_CLIENT_DEFAULT_PORT 2400 //client默认port #define TCP_SERVER_DEFAULT_IP 192,168,16,104 //server默认IP地址 #define TCP_SERVER_DEFAULT_PORT 8888 //server默认port #define TCP_SEND_TIME_OUT 5 //数据发送超时时间,单位S #define UDP_LOCAL_PORT 8000 //UDP连接本地port #define UDP_REMOTE_PORT 8899 //UDP连接远程port #define UDP_SERVER_PORT 8100 //UDPserver本地port
//数据port调度
//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; } }调用这个实现将clientport设置为0,这样就能够接受来自随意port的数据
udp_ServerSendEndCallBack(i); //数据发送完毕后一定要调用回调函数
//初始化并处理UDPserver数据
//实现收到后马上返回数据
udp_server_connected(UDP_SERVER_PORT, 0); //新建UDP服务器,client随意port
//UDP服务器数据处理 if(udp_server.RxLen > 0) { uart_printf("服务器port:%d\r\n",udp_server.ServerPort); uart_printf("clientport:%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; }