uip UDP 服務器廣播模式(客戶端可以任意端口,并且主動向客戶端發(fā)送數(shù)據(jù))
目前移植uip,發(fā)現(xiàn)UDP 服務器模式下,必須指定本地端口以及客戶端端口,否則只能講客戶端端口設置為0,才能接收任意端口的數(shù)據(jù),但是無法發(fā)送數(shù)據(jù),因為此時客戶端端口設置為0了,我通過將原始數(shù)據(jù)包中的客戶端端口保存下來,并且在發(fā)送的時候將客戶端端口替換為指定的端口,發(fā)送完成之后又設置為0,這樣就實現(xiàn)了向任意客戶端端口發(fā)送數(shù)據(jù).
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)?&&
這句就限制了客戶端端口為0或者指定端口
//udp_server.c
/*************************************************************************************************************
?*?文件名: udp_server.h
?*?功能: uIP?UDP服務器相關函數(shù)
?*?作者: cp1300@139.com
?*?創(chuàng)建時間: 2014-06-04
?*?最后修改時間: 2014-06-04
?*?詳細: UDP服務器相關函數(shù)
*************************************************************************************************************/
#include?"SYSTEM.h"
#include?"tapdev.h"
#include?"uip.h"
#include#include #include?"uIP_user.h"
#include?"udp_server.h"
#include?"appconfig.h"
u16?UDP_ServerPort?=?UDP_SERVER_PORT; //UDP服務器本地端口,用于新數(shù)據(jù)端口識別
UIP_USER?udp_server; //UDP?服務器數(shù)據(jù)結構
static?bool?isAnyPort?=?FALSE; //客戶端任意端口標志
/*************************************************************************************************************************
*?函數(shù) : void?udp_server_connected(u16?ServerPort,u16?ClientPort)
*?功能 : 建立一個UDP服務器(廣播方式)
*?參數(shù) : 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; //客戶端任意端口
}
}
/*************************************************************************************************************************
*?函數(shù) : void?udp_server_appcall(void)
*?功能 : 服務器回調(diào)函數(shù),用于uip處理數(shù)據(jù)
*?參數(shù) : 無
*?返回 : 無
*?依賴 : 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); //復制接收的數(shù)據(jù)到接收緩沖區(qū)
udp_server.RxLen?=?uip_len; //存儲接收數(shù)據(jù)長度
udp_server.ClientPort?=?(u16)(uip_buf[34]<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); //暫時將客戶端端口設置為上一次發(fā)送數(shù)據(jù)的客戶端端口
}
/*************************************************************************************************************************
*?函數(shù) : void?udp_ServerSendEndCallBack(u16?conn)
*?功能 : UDP發(fā)送數(shù)據(jù)完成回調(diào)函數(shù),目前只支持一個服務器端口
*?參數(shù) : pBuff:發(fā)送數(shù)據(jù)緩沖區(qū),len:發(fā)送數(shù)據(jù)長度,ClientPort:客戶端端口
*?返回 : 無
*?依賴 : uip
*?作者 : cp1300@139.com
*?時間 : 2014-06-04
*?最后修改時間 :? 2014-06-05
*?說明 :? 由于UDP服務器的客戶端IP設置為0后可以接收任意端口發(fā)來的數(shù)據(jù),但是卻無法發(fā)送數(shù)據(jù)
到0端口,因此在發(fā)送前將客戶端端口設置為實際端口,發(fā)送完成后修改為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服務器相關函數(shù) ?*?作者: cp1300@139.com ?*?創(chuàng)建時間: 2014-06-04 ?*?最后修改時間: 2014-06-04 ?*?詳細: UDP服務器相關函數(shù) *************************************************************************************************************/ #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?服務器數(shù)據(jù)結構 extern?u16?UDP_ServerPort; //UDP服務器本地端口 void?udp_server_connected(u16?ServerPort,u16?ClientPort); //建立一個UDP服務器(廣播方式) void?udp_server_appcall(void); //服務器回調(diào)函數(shù),用于uip處理數(shù)據(jù) void?udp_ServerSendDataPackage(u8?*pBuff,?u16?len,u16?ClientPort); //UDP?服務器發(fā)送數(shù)據(jù) void?udp_ServerSendEndCallBack(u16?conn); //UDP發(fā)送數(shù)據(jù)完成回調(diào)函數(shù) #endif?//_UDP_SERVER_H_
//結構體定義
//用戶連接數(shù)據(jù)結構
#define?UIP_RX_BUFF_ZISE 512 //接收數(shù)據(jù)緩沖區(qū)大小
#define?UIP_TX_BUFF_ZISE 512 //發(fā)送數(shù)據(jù)緩沖區(qū)大小
typedef?struct
{
u16?RxLen; //接收數(shù)據(jù)長度
u16 TxLen; //發(fā)送數(shù)據(jù)長度
u16?ClientPort; //客戶端端口
u16 ServerPort; //服務器端口
u8 RxBuff[UIP_RX_BUFF_ZISE]; //接收緩沖區(qū)
u8 TxBuff[UIP_TX_BUFF_ZISE]; //接收緩沖區(qū)
}UIP_USER;
//配置定義
#define?DHCP_TIME_OUT 60 //DHCP獲取超時時間,單位S #define?TCP_LINK_SERVER_TIME_OUT 10 //連接服務器超時時間,單位S #define?TCP_LINK_SERVER_CNT 5 //連接服務器重試次數(shù) #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 //數(shù)據(jù)發(fā)送超時時間,單位S #define?UDP_LOCAL_PORT 8000 //UDP連接本地端口 #define?UDP_REMOTE_PORT 8899 //UDP連接遠程端口 #define?UDP_SERVER_PORT 8100 //UDP服務器本地端口
//數(shù)據(jù)端口調(diào)度
//UDP應用接口函數(shù)(UIP_UDP_APPCALL)
void?udp_appcall(void)
{
switch(uip_udp_conn->lport)//本地監(jiān)聽端口
{
//用于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調(diào)度處理,必須在數(shù)據(jù)發(fā)送完成后調(diào)用自定義的回調(diào)函數(shù)
for(i?=?0;?i?<?UIP_UDP_CONNS;?i++)
{
//只處理發(fā)送事件
uip_udp_periodic(i); //處理UDP通信事件
//當上面的函數(shù)執(zhí)行后,如果需要發(fā)送數(shù)據(jù),則全局變量uip_len>0
//需要發(fā)送的數(shù)據(jù)在uip_buf,?長度是uip_len?(這是2個全局變量)
if(uip_len?>?0)
{
LED2?=?~?LED2;
uip_arp_out();//加以太網(wǎng)頭結構,在主動連接時可能要構造ARP請求
tapdev_send();//發(fā)送數(shù)據(jù)到以太網(wǎng)
udp_ServerSendEndCallBack(i); //數(shù)據(jù)發(fā)送完成后一定要調(diào)用回調(diào)函數(shù)
break;
}
}調(diào)用這個實現(xiàn)將客戶端端口設置為0,這樣就可以接受來自任意端口的數(shù)據(jù)
udp_ServerSendEndCallBack(i); //數(shù)據(jù)發(fā)送完成后一定要調(diào)用回調(diào)函數(shù)
//初始化并處理UDP服務器數(shù)據(jù)
//實現(xiàn)收到后立即返回數(shù)據(jù)
udp_server_connected(UDP_SERVER_PORT,?0); //新建UDP服務器,客戶端任意端口
//UDP服務器數(shù)據(jù)處理
if(udp_server.RxLen?>?0)
{
uart_printf("服務器端口:%drn",udp_server.ServerPort);
uart_printf("客戶端端口:%drn",udp_server.ClientPort);
uart_printf("UDP?Server?Rx(%dB):%srn",udp_server.RxLen,(char*)udp_server.RxBuff);
udp_ServerSendDataPackage(udp_server.RxBuff,?udp_server.RxLen,?udp_server.ClientPort);
udp_server.RxLen?=?0;
}//仿真結果





