|
【初始化代碼】 void myapp_init(uip_ipaddr_t *ipaddr) { // UDP端口監聽 uip_ipaddr(ipaddr, 192, 168, 1, 2); // 客戶端IP uconn = uip_udp_new(ipaddr, HTONS(82)); // 客戶端端口號 uip_udp_bind(uconn, HTONS(12345)); // 本機端口號 }
|
|
【UDP回調函數】 void uip_udp_appcall(void) { char buf[20];
// 定期檢測事件 if (uip_poll()) { if (send_udp_packet) // 如果該變量為1,則無條件發送一個UDP數據包 { strcpy_P(uip_appdata, PSTR("This is a string.")); uip_udp_send(strlen(uip_appdata)); send_udp_packet = 0; } } // 若收到了UDP數據包 if (uip_newdata()) { // 提取數據包前19位元組內容到buf中 if (uip_len >= sizeof(buf)) uip_len = sizeof(buf) - 1; strncpy(buf, uip_appdata, uip_len); buf[uip_len] = '\0';
// 組裝生成新數據包 strcpy_P(uip_appdata, PSTR("New data arrived: ")); strcat(uip_appdata, buf);
// 發送回應 uip_udp_send(strlen(uip_appdata)); // 由於當ARP緩存表中沒有客戶端MAC地址時,uip會用ARP請求數據包把uip_appdata中的內容給覆蓋掉 // 只發送ARP請求而不發送數據包內容 // 因此第一次發送的數據包很可能會丟失 } }
|
|
【PC端測試用的Java程序】 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException;
public class Sender { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(82); // 本機端口 byte[] data = "Hello,_World!_This_is_a_long_string.".getBytes(); DatagramPacket dp = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.50"), 12345); // 服務器IP位址和端口號 System.out.println("Begin..."); ds.send(dp); System.out.println("Sent!"); data = new byte[100]; dp = new DatagramPacket(data, data.length); ds.receive(dp); System.out.println("Recved: " + new String(data, 0, dp.getLength())); ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } 【運行結果】 Begin... Sent! Recved: New data arrived: Hello,_World!_This_
|
|
【UDP監聽任意端口的方法】 uip_ipaddr(ipaddr, 0, 0, 0, 0); uconn = uip_udp_new(ipaddr, 0); // 可監聽任意客戶端任意端口 uip_udp_bind(uconn, HTONS(12345)); // 但必須指定本機端口號
|
|
#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
void uip_udp_appcall(void) { char buf[20];
// 定期檢測事件 // 現在沒有客戶端IP位址和端口號了, 所以下面這段代碼不能正常工作 /* if (uip_poll()) { if (send_udp_packet) // 如果該變量為1,則無條件發送一個UDP數據包 { strcpy_P(uip_appdata, PSTR("This is a string.")); uip_udp_send(strlen(uip_appdata)); send_udp_packet = 0; } } */ // 若收到了UDP數據包 if (uip_newdata()) { // 提取數據包前19位元組內容到buf中 if (uip_len >= sizeof(buf)) uip_len = sizeof(buf) - 1; strncpy(buf, uip_appdata, uip_len); buf[uip_len] = '\0';
// 根據客戶端的地址修改當前UDP連接, 否則回應數據包將無法發送出去 // 修改後該連接(uconn)將只能接收該客戶端的數據包 // 這個問題只能通過修改uip.c中標籤udp_send:的代碼解決 uip_ipaddr_copy(uip_udp_conn->ripaddr, UDPBUF->srcipaddr); // 獲取客戶端IP位址 uip_udp_conn->rport = UDPBUF->srcport; // 獲取客戶端端口號
// 組裝生成新數據包 strcpy_P(uip_appdata, PSTR("New data arrived: ")); strcat(uip_appdata, buf); // 附上客戶端的IP位址和端口號信息 sprintf_P(buf, PSTR("\nIP: %d.%d.%d.%d"), uip_udp_conn->ripaddr[0] & 0xff, uip_udp_conn->ripaddr[0] >> 8, uip_udp_conn->ripaddr[1] & 0xff, uip_udp_conn->ripaddr[1] >> 8); strcat(uip_appdata, buf); sprintf_P(buf, PSTR("\nPort: %d"), ntohs(uip_udp_conn->rport)); strcat(uip_appdata, buf);
// 發送回應 uip_udp_send(strlen(uip_appdata)); // 由於當ARP緩存表中沒有客戶端MAC地址時,uip會用ARP請求數據包把uip_appdata中的內容給覆蓋掉 // 只發送ARP請求而不發送數據包內容 // 因此第一次發送的數據包很可能會丟失 } }
|
|
【運行結果】 Begin... Sent! Recved: New data arrived: Hello,_World!_This_ IP: 192.168.1.2 Port: 82
|
|
如果不修改uip的原始碼,則只能實現一次性監聽任意客戶端。監聽成功後將只能從該客戶端收發數據。
|