基于PLC1850平台的UDP报文接收与发送

一、UDP报文格式

  源端口(2个字节):发送报文的进程的16位端口号。

  目的端口(2个字节):目的设备上的接收进程的16位端口号。

  长度(2个字节):整个UDP数据报的长度,包括首都和数据字段。

  校验和(2个字节):提供错误检测功能的16位校验和,为可选项。

  数据(可变长度):要发送已封存应用报文。

2、UDP封装

3、UDP校验和计算

  UDP校验和是所计算字段的16位反码和的反码,用IP数据报的某些字段组成一个伪首部,再与UDP报文合在一起计算校验和。因此,校验和是对伪首部、UDP首部和UDP数据的计算结果。如果需要,数据后面可能会填以数值为0的字节,使得数据字节数为两字节的整数倍。

4、发送UDP报文

  通过java语言编写一个UDP数据报发送个LPC1850平台,程序代码如下:

 1 /**
 2  * @Author CFF
 3  * @Date:Created in 22:45 2019/4/20
 4  */
 5 import java.net.DatagramSocket;
 6 import java.net.DatagramPacket;
 7 import java.net.InetAddress;
 8 
 9  public class udp {
10  public static void main(String[] args ) throws Exception {
11          String content = "ABCDEFGHIJ";
12          byte [] sentBuf = content .getBytes( "GBK" );
13          DatagramSocket client = new DatagramSocket();
14          InetAddress destinationAddress =InetAddress. getByName ( "192.168.1.190" );
15          int port =2425;
16          DatagramPacket sendPacket = new DatagramPacket( sentBuf , sentBuf.length , destinationAddress , port );
17          client .send(sendPacket);
18          client .close();
19     }
20 }

5、LPC1850代码

  LPC1850 Internet初始化主函数,代码如下:

 1 #include "LPC18xx.h"
 2 #include "led.h"
 3 
 4 
 5 extern void taskEth (void);
 6 
 7 int main(void)
 8 {
 9     SystemInit();
10 
11     ledInit();
12     SysTick_Config(GetCoreClock() / 1000);
13 
14     taskEth();
15 
16     while (1);  
17 }
18 
19 void SysTick_Handler(void)
20 {
21     static int counter = 0;
22 
23     counter++;
24     if (counter >= 100)
25     {
26         counter = 0;
27         ledRolling();
28     }
29 }

  EthTask.c代码如下:

 1 #include <stdlib.h>
 2 #include <lpc18xx.h>
 3 #include "lpc18xx_emac.h"
 4 #include "lpc18xx_debug.h"
 5 
 6 extern uint32_t ipatol(char * p_input);
 7 extern void ipInit(uint8_t * mac, uint32_t ip);
 8 extern uint32_t ipRcvMacFrame(uint8_t * block, uint32_t frameLen);
 9 
10 uint8_t gFlag = 0;
11 
12 uint8_t g_emacBuffer[2048];
13 
14 uint8_t g_ethMac[6];
15 
16 // EMAC½Ó¿Ú½ÓÊÕµ½Êý¾Ý£¬Í¨ÖªÓ¦ÓòãµÄ»Øµ÷º¯Êý¡£
17 void ethReadReadyCb()
18 {
19     gFlag = 1;
20 }
21 
22 void taskEth (void)
23 {    
24     uint32_t len;
25 
26     g_ethMac[0] = 0x11;
27     g_ethMac[1] = 0x1F;
28     g_ethMac[2] = 0xE0;
29     g_ethMac[3] = 0x12;
30     g_ethMac[4] = 0x1E;
31     g_ethMac[5] = 0x0F;
32 
33     debugComInit();
34     uartPrint("uart init\r\n");
35 
36     while (ethInit(ethReadReadyCb, g_ethMac) == 0);
37 
38     uartPrint("eth init complete\r\n");
39     // ΪÒÔÌ«Íø½Ó¿ÚÖ¸¶¨MACµØÖ·ºÍIPµØÖ·
40     ipInit(g_ethMac, 0xBE01A8C0);   // 192.168.1.190
41 
42     while (1)
43     {
44         if (!gFlag)
45         {
46             continue;
47         } 
48 
49         len = ethRead(g_emacBuffer, 2048); 
50         if (len)
51         {
52             ipRcvMacFrame((uint8_t *)g_emacBuffer, len);
53         }
54         gFlag = 0;
55     }
56 }

  ip.c代码如下:

  1 #include <stdint.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include "lpc18xx_emac.h"
  5 #include "lpc18xx_debug.h"
  6 //#include "shell.h"
  7 
  8 #define MAC_TYPE_IP   0x0800  //ipÀàÐÍ
  9 #define MAC_TYPE_ARP  0x0806  //macÀàÐÍ
 10 
 11 #define ARP_REQ 0x0001      //ARPÇëÇó
 12 #define ARP_RSP 0x0002        //ARPÏìÓ¦
 13 
 14 #define ICMP_ECHO_REQUEST    8                   // message is an echo request
 15 #define ICMP_ECHO_REPLY      0                   // message is an echo reply
 16 
 17 #define PROT_ICMP            1                   // Internet Control Message Protocol
 18 #define PROT_TCP             6                   // Transmission Control Protocol
 19 #define PROT_UDP             17                  // User Datagram Protocol
 20 
 21 #define DONT_FRAGMENT       0x4000 //fragment
 22 #define MORE_FRAGMENT       0x2000
 23 #define FRAGMENT_OFFSET     0x1FFF
 24 
 25 uint8_t * UDPChecksum;
 26 uint8_t g_ethMacAddr[6];
 27 uint32_t g_ethIpAddr;
 28 
 29 uint32_t g_ipSndBuffer[64];
 30 
 31 uint16_t g_ipIdentifier = 0;
 32 
 33 // ½«×Ö´ÓÖ÷»úÐòתΪÍøÂçÐò
 34 uint16_t htons(uint16_t word)
 35 {
 36     return ((word >> 8) & 0x00FF) | ((word << 8) & 0xFF00);
 37 }
 38 
 39 // ½«×Ö´ÓÍøÂçÐòתΪÖ÷»úÐò
 40 uint16_t ntohs(uint16_t word)
 41 {
 42     return ((word >> 8) & 0x00FF) | ((word << 8) & 0xFF00);
 43 }
 44 
 45 
 46 uint16_t calcChecksum(uint16_t * buffer, uint32_t size)   
 47 {   
 48     uint32_t cksum;   
 49     
 50     cksum = 0;   
 51 
 52     while (size > 1)   
 53     {   
 54         cksum += *buffer++;   
 55         size -= sizeof(uint16_t);         
 56     }   
 57 
 58     if (size)   
 59     {   
 60         cksum += *(uint8_t*)buffer;         
 61     }   
 62 
 63     cksum = (cksum >> 16) + (cksum & 0xffff);   
 64     cksum += (cksum >>16);     
 65     
 66     return (uint16_t)(~cksum);     
 67 }
 68 
 69 // ·¢ËÍARPÏìÓ¦
 70 void arpSndRsp(uint32_t dstIp, uint8_t * mac)
 71 {
 72     uint8_t * block;
 73     //uint32_t blockLen;
 74 
 75     block = (uint8_t *)g_ipSndBuffer;
 76 
 77     memcpy(block, mac, 6);
 78 
 79     memcpy(block + 6, g_ethMacAddr, 6);
 80 
 81     // arp type
 82     *(uint16_t *)&block[12] = htons(MAC_TYPE_ARP);
 83 
 84     // --------- ARP ²ã
 85     
 86     // Hardway type : Ethernet
 87     block[14] = 0x00;
 88     block[15] = 0x01;
 89 
 90     // ip type
 91     *(uint16_t *)&block[16] = htons(MAC_TYPE_IP);
 92 
 93     // Hardway size
 94     block[18] = 0x06;
 95 
 96     // Protocal size
 97     block[19] = 0x04;
 98 
 99     // arp reply
100     *(uint16_t *)&block[20] = htons(ARP_RSP);
101 
102     // Sender MAC address
103     memcpy(block + 22, g_ethMacAddr, 6);
104 
105     // Sender IP address
106     *(uint32_t *)&block[28] = g_ethIpAddr;
107 
108     // Target MAC address
109     memcpy(block + 32, mac, 6);
110 
111     // Target IP address : 192.168.0.67
112     block[38] = (uint8_t)dstIp;
113     block[39] = (uint8_t)(dstIp >> 8);
114     block[40] = (uint8_t)(dstIp >> 16);
115     block[41] = (uint8_t)(dstIp >> 24);
116 
117     // 18¸öÌî³ä×Ö½Ú
118     memset(block + 42, 0, 18);
119 
120     ethWrite((uint8_t *)block, 60);
121 }
122 
123 void arpRcv(uint8_t * block, uint32_t frameLen)
124 {
125     uint32_t srcIp, dstIp;
126     uint16_t msgType;
127                
128     msgType = ntohs(*(uint16_t *)(block+6));   
129 
130     srcIp = (uint32_t)*(uint16_t *)(block + 14);
131     srcIp|= ((uint32_t)*(uint16_t *)(block + 16)) << 16;
132 
133     dstIp = (uint32_t)*(uint16_t *)(block + 24);
134     dstIp|= ((uint32_t)*(uint16_t *)(block + 26)) << 16;
135 
136     if (dstIp != g_ethIpAddr)
137     {
138         return;
139     }
140 
141     if (msgType == ARP_REQ)
142     {
143         arpSndRsp(srcIp, block + 8);
144     }
145 }
146 
147 // ²»¹Ü³É¹¦Óë·ñ,¶¼ÓÉIP²ãÀ´ÊÍ·ÅÊý¾Ý°ü¡£
148 void ipSnd(uint32_t dstIp, uint8_t * block, uint32_t len, uint8_t protoType, uint8_t * mac)
149 {
150     block-= 20;
151     len+= 20;
152     
153     // ------------ IP ²ã
154     
155     block[0] = 0x45;  // IP V4.  length 20(5*4)
156     
157     block[1] = 0x00;  // service
158     
159     *(uint16_t *)&block[2] = htons(len);
160     
161     *(uint16_t *)&block[4] = htons((uint16_t)g_ipIdentifier++); // identification
162     
163     *(uint16_t *)&block[6] = 0x0040; // flag and fragment
164 
165     block[8] = 128;  // TTL
166 
167     block[9] = protoType;
168     
169     *(uint16_t *)&block[10] = 0; // УÑéºÍÏÈÌîÉÏ0
170     
171     *(uint16_t *)&block[12] = (uint16_t)g_ethIpAddr;
172     *(uint16_t *)&block[14] = (uint16_t)(g_ethIpAddr >> 16);
173 
174     *(uint16_t *)&block[16] = (uint16_t)dstIp;
175     *(uint16_t *)&block[18] = (uint16_t)(dstIp >> 16);
176     
177     *(uint16_t *)&block[10] = calcChecksum((uint16_t *)block, 20);
178 
179     // ------------ MAC ²ã
180 
181     block-= 14;
182     len+= 14;
183     
184     memcpy(block, mac , 6);
185     
186     memcpy(block + 6, g_ethMacAddr, 6);
187 
188     *(uint16_t *)&block[12] = htons(MAC_TYPE_IP);
189 
190     if (len < 60)
191     {
192         // MACÖ¡Ì«¶Ì£¬²¹µ½×î¶Ì³¤¶È¡£
193         memset(block + len, 0, 60 - len);
194         len = 60;
195     }
196 
197     ethWrite((uint8_t *)block, len);
198 }
199 
200 // ICMPÊÕµ½ÇëÇó£¬ÐèÒª»ØÏìÓ¦¡£
201 void icmpRcvRequest(uint32_t srcIp, uint8_t * icmp, uint32_t len, uint8_t * mac)
202 {
203     uint8_t * block;
204 
205     block = (uint8_t *)g_ipSndBuffer;
206 
207     // Áô³ö 14(MAC)+20(IP)¸ö×Ö½Ú   
208     block+=(14+20);
209     
210     // ----------- ICMP ²ã
211     memcpy(block, icmp, len);
212     
213     block[0] = ICMP_ECHO_REPLY;
214     block[1] = 0;   // code
215     
216     *(uint16_t *)&block[2] = 0;  // УÑéºÍÏÈÌîÉÏ0
217     
218     *(uint16_t *)&block[2] = calcChecksum((uint16_t *)block, len);
219 
220     ipSnd(srcIp, (void *)block, len, PROT_ICMP, mac);
221 }
222 void udpsend(uint32_t srcIp, uint8_t * udp, uint32_t len, uint8_t * mac)
223 {
224         uint8_t * block;
225     int i;
226       char sendData[10]={'R','e','c','e','i','v','e','.','.','.'};
227     block = (uint8_t *)g_ipSndBuffer;
228     // Áô³ö 14(MAC)+20(IP)¸ö×Ö½Ú   
229     block+=(14+20);
230         memcpy(block,udp,len);
231     
232         memcpy(block,udp+2,2);
233         memcpy(block+2,udp,2);
234   
235         for(i=0;i<10;i++)
236         {
237             block[8+i]=sendData[i];
238         }
239         
240         *(uint16_t *)&block[4] = htons(len);
241         
242         *(uint16_t *)&block[6] = 0;// УÑéºÍÏÈÌîÉÏ0
243         
244         *(uint16_t *)&UDPChecksum[10]=htons(len);
245         memcpy(UDPChecksum+11,block,len);
246         *(uint16_t *)&block[6] = calcChecksum((uint16_t *)UDPChecksum, len+12);
247         uartPrint("Checksum:0x%04x\r\n",ntohs(*(uint16_t *)&block[6]));
248         ipSnd(srcIp, (void *)block, len, PROT_UDP, mac);
249 }
250 //udp½ÓÊÕ
251 void udpRcv(uint32_t srcIp,uint8_t * udp, uint32_t len, uint8_t * mac)
252 {
253     int i;
254     uartPrint("Recevie UDP message:\r\n");
255     uartPrint("UDP Head:\r\n");
256     uartPrint("Source Port:%d\r\n",ntohs(*(uint16_t *)(udp)));
257     uartPrint("Destination Port:%d\r\n",ntohs(*(uint16_t *)(udp+2)));
258     uartPrint("Total Length:%d bytes\r\n",ntohs(*(uint16_t *)(udp+4)));
259     uartPrint("Checksum:0x%04x\r\n",ntohs(*(uint16_t *)(udp+6)));
260     uartPrint("UDP Data:\r\n");
261     for(i=0;i<len-8;i++)
262     {
263         uartPrint("%c",udp[8+i]);
264     }
265     uartPrint("\r\nsending UDP Data...\r\n");    
266     udpsend(srcIp, udp, len, mac);
267     uartPrint("sent UDP Data.\r\n\r\n");
268 }
269 // ½ÓÊÕµ½IP°üµÄ´¦Àí
270 void ipRcv(uint8_t * frame, uint32_t frameLen, uint8_t * mac)
271 {
272     uint16_t ipLength, flag;
273     uint32_t srcIp, dstIp;
274 
275     if (frameLen < 20)
276     {
277         return;
278     }
279 
280     if (calcChecksum((uint16_t *)frame, 20))
281     {
282         // УÑéºÍ²»ÕýÈ·
283         return;
284     }
285 
286     if (frame[0] != 0x45)
287     {
288         // IP VERSION ӦΪ4£¬³¤¶ÈӦΪ20£¨5¸öbit32£©×Ö½Ú¡£
289         return;
290     }
291 
292     // ignore Type Of Service
293     
294     ipLength = ntohs(*(uint16_t *)&frame[2]);
295 
296     // ignore identification
297 
298     flag = ntohs(*(uint16_t *)&frame[6]);
299 
300     if (!(flag & DONT_FRAGMENT))
301     {
302         // IP¿ÉÒÔ±»·Ö°ü£¬µ«ÎÒÃÇÖ»´¦Àí²»·Ö°üµÄÇé¿ö¡£
303         
304         if (flag & MORE_FRAGMENT)
305         {
306             // ·Ç×îºóµÄÒ»°ü£¬¶ªÆú¡£
307             return;
308         }
309         
310         // ÊÇ×îºóÒ»°ü¡£
311         
312         if (flag & FRAGMENT_OFFSET)
313         {
314             // ÊÇ×îºóÒ»°ü£¬ÇÒÆ«ÒÆÁ¿²»Îª0£¬Ò²¶ªÆú¡£
315             return;
316         }
317         
318         // ×îºóÒ»°ü£¬ÇÒÆ«ÒÆÁ¿Îª0£¬ÊÇÕû°ü£¬´¦Àí£¡
319     }
320     
321     if (frameLen < ipLength)
322     {
323         return;
324     }
325     
326     // ignore fragment offset
327 
328     //ttl = (uint32_t)frame[8];
329 
330     //srcIp = (frame[12] | (frame[13]<< 8) | (frame[14] << 16) | (frame[15] << 24));
331     //dstIp = (frame[16] | (frame[17]<< 8) | (frame[18] << 16) | (frame[19] << 24));
332 
333     srcIp = *(uint16_t *)(frame + 12) | ((uint32_t)*(uint16_t *)(frame + 14) << 16);
334     dstIp = *(uint16_t *)(frame + 16) | ((uint32_t)*(uint16_t *)(frame + 18) << 16);
335 
336     if ((dstIp != g_ethIpAddr) && (dstIp != 0x0100007F) && (dstIp != 0xffffffff))
337     {
338         return;
339     }
340 
341 //    if (frame[9] != PROT_ICMP)
342 //    {
343 //        // ·ÇICMP°ü£¬Ôݲ»´¦Àí
344 //        return;
345 //    }
346         if(frame[9] == PROT_UDP)
347         {
348             //αͷ²¿
349             UDPChecksum=(uint8_t *)g_ipSndBuffer;
350             memcpy(UDPChecksum,frame+12,4);
351             memcpy(UDPChecksum+4,frame+16,4);
352             UDPChecksum[8]=0;
353             UDPChecksum[9]=frame[9];
354             udpRcv(srcIp,frame + 20, ipLength - 20,mac);
355         }
356 
357     if (frame[20] == ICMP_ECHO_REQUEST)
358     {
359         icmpRcvRequest(srcIp, frame + 20, ipLength - 20, mac);
360     }
361 }
362 
363 
364 // IP²ã½ÓÊÕMAC²ãÊý¾ÝÖ¡µÄº¯Êý
365 uint32_t ipRcvMacFrame(uint8_t * block, uint32_t frameLen)
366 {
367     //0xFFFF ¹ã²¥·½Ê½
368     if ( ((*(uint16_t *)block == 0xFFFF) && (*(uint16_t *)(block + 2) == 0xFFFF) && (*(uint16_t *)(block + 4) == 0xFFFF))
369        ||(memcmp(block, g_ethMacAddr, 6) == 0))
370     {
371         // ÊÇ·¢¸ø±¾»úµÄ¡£
372         switch (ntohs(*(uint16_t *)(block+12)))
373         {
374         case MAC_TYPE_ARP:
375             arpRcv(block + 14, frameLen -14);
376             break;
377         case MAC_TYPE_IP:
378             ipRcv(block + 14, frameLen - 14, block+6);
379             break;
380         default:
381             break;
382         }
383     }
384     return 1;
385 }
386 
387 void ipInit(uint8_t * mac, uint32_t ip)
388 {
389     memcpy(g_ethMacAddr, mac, 6);
390     g_ethIpAddr = ip;
391 }

  通过上面代码,实现UDP报文接收与发送,实现UDP数据通讯。

 

posted @ 2019-04-23 10:00  嗨_放飞梦想  阅读(990)  评论(0编辑  收藏  举报