因为使用IEC61850需要直接访问以太网数据链路层,因此需要做一些访问数据链路层的准备工作。计划使用Linux C构造UDP原始帧在局域网内广播消息,并在另一台电脑上使用QT程序接收和显示这个广播消息。

网上关于使用RAW SOCKET构造原始帧的资料很少,在外国的一个网站上找到了一份源码,经过改造后可以再局域网内广播UDP了。 在此之前遇到了很多问题,在此总结:

(1)使用wireshark可以抓取到UDP数据帧,但应用层的QT程序就是不能读到这个UDP中的数据。经测试,这可能是因为UDP段的校验和错误,wireshark并不会报错,但该UDP无法被应用层的程序接收(经过本人测试)。

(2)以为identification(ID)的值对于发送只有一个数据帧的UDP会产生影响。经测试,如果UDP只有一个数据帧,则identification可以取任意值,不会影响UDP消息的正确接收。

(3)构造UDP原始帧的Linux C程序和接收UDP消息的QT程序若放在同一台计算机下测试,则无法接收到广播的UDP消息;若将两个程序分别放在两台不同的计算机下运行,则UDP广播消息可被正确地接收。(本人分析的原因:本机上发送的UDP广播可能不会广播给自身,从而导致了在同一台计算机上不能正确接收)

(4)为何wireshark抓到的UDP原始帧中最后几位为"00",wireshark显示其属于trailer。在以太网中,规定最小的数据包为64字节(和碰撞检测有关),如果数据包不足64字节,则会由网卡填充,所以显示到后面几位就是"00"。

(5)以太网帧的最小长度到底是多少?不是64字节么?为什么看到了42字节的arp包?  是64字节,你用wireshark抓到的包是把最后4个字节的FCS丢掉的结果,在没有达到64字节时,网卡驱动会自动填充到64字节。楼主看到的42字节,可能是wireshark做了处理,去掉了填充部分。

在这个过程中其实遇到了很多问题,就不一一列举了,再好的文字都不如代码来的实在,下面是一些源码:

【1】接收UDP消息的QT程序

[cpp]  view plain copy
  1. /**
  2. *这个程序功能很简单:监听6666端口的UDP消息,如果接收到消息则显示。
  3. */
  4. #include "mainwindow.h"
  5. #include "ui_mainwindow.h"
  6. MainWindow::MainWindow(QWidget *parent) :
  7. QMainWindow(parent),
  8. ui(new Ui::MainWindow)
  9. {
  10. ui->setupUi(this);
  11. socket=new QUdpSocket(this);
  12. connect(ui->startButton,SIGNAL(clicked()),this,SLOT(startDo()));
  13. connect(ui->clearButton,SIGNAL(clicked()),ui->historyTextEdit,SLOT(clear()));
  14. connect(ui->quitButton,SIGNAL(clicked()),this,SLOT(quitDo()));
  15. }
  16. MainWindow::~MainWindow()
  17. {
  18. delete ui;
  19. }
  20. bool MainWindow::validatePort(QString port)
  21. {
  22. bool ok=false;
  23. int tmp_port=port.toInt(&ok,10);
  24. if(ok){
  25. if((tmp_port>1024)&&(tmp_port<65536)){
  26. return true;
  27. }else{
  28. return false;
  29. }
  30. }else{
  31. return false;
  32. }
  33. }
  34. //初始化程序UDP相关的部分
  35. void MainWindow::startDo()
  36. {
  37. QString port=ui->portEdit->text();
  38. bool bo=validatePort(port);
  39. if(bo && (port != "")){
  40. bool ok=socket->bind((quint16)port.toInt());
  41. if(ok){
  42. ui->historyTextEdit->append("bind indicated port!");
  43. }else{
  44. ui->historyTextEdit->append("bind error!");
  45. }
  46. }else{
  47. bool ok=socket->bind(DEFAULT_PORT);
  48. if(ok){
  49. ui->historyTextEdit->append("bind default port!");
  50. }else{
  51. ui->historyTextEdit->append("bind error!");
  52. }
  53. }
  54. connect(socket,SIGNAL(readyRead()),this,SLOT(readData()));
  55. ui->startButton->setEnabled(false);
  56. }
  57. //读取UDP数据报中的信息
  58. void MainWindow::readData()
  59. {
  60. while(socket->hasPendingDatagrams()){
  61. QByteArray arr;
  62. arr.resize(socket->pendingDatagramSize());
  63. socket->readDatagram(arr.data(),arr.size());
  64. ui->historyTextEdit->append(arr);
  65. }
  66. }
  67. void MainWindow::quitDo()
  68. {
  69. exit(0);
  70. }

通过了测试的Linux C UDP原始帧构造程序有两个,便于参考。

【2】Linux C UDP构造参考程序一

[cpp]  view plain copy
  1. /**
  2. *功能:构造UDP 原始帧,并使用Linux原始套接字发送到局域网中。
  3. *UDP数据帧中包含了一个测试用的字符串“123456789”
  4. **/
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <netinet/if_ether.h>
  8. #include <netinet/ip.h>
  9. #include <linux/if_packet.h>
  10. #include <linux/if.h>
  11. #include <linux/sockios.h>
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. int main(void)
  15. {
  16. int fd=0;
  17. char buf[256]={0};
  18. struct sockaddr_ll dest;
  19. int destlen=0;
  20. int ret=0;
  21. struct ifreq ifstruct;
  22. fd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
  23. if(fd<0){
  24. printf("ERR:socket was failed.\n");
  25. return -1;
  26. }
  27. memset((char *)&dest, 0x00,sizeof(dest));
  28. destlen=sizeof(dest);
  29. strcpy(ifstruct.ifr_name, "eth0");
  30. ioctl(fd, SIOCGIFINDEX, &ifstruct);
  31. dest.sll_ifindex=ifstruct.ifr_ifindex;
  32. dest.sll_family=AF_PACKET;
  33. unsigned char my_mac[]={0x08,0x00,0x27,0x93,0x68,0xe5};
  34. memcpy(dest.sll_addr,my_mac,6);
  35. dest.sll_halen=ETH_ALEN;
  36. memset(buf,0x00,sizeof(buf));
  37. int j=0;
  38. buf[0]=0xff;
  39. buf[1]=0xff;
  40. buf[2]=0xff;
  41. buf[3]=0xff;
  42. buf[4]=0xff;
  43. buf[5]=0xff;
  44. buf[6]=0x00;
  45. buf[7]=0x11;
  46. buf[8]=0x22;
  47. buf[9]=0x33;
  48. buf[10]=0x00;
  49. buf[11]=0x00;
  50. buf[12]=0x08;
  51. buf[13]=0x00;   //protocal field
  52. buf[14]=0x45;
  53. buf[15]=0x00;
  54. buf[16]=0x00;
  55. buf[17]=0x25;
  56. buf[18]=0x00;
  57. buf[19]=0x00;
  58. buf[20]=0x40;
  59. buf[21]=0x00;
  60. buf[22]=0x40;
  61. buf[23]=0x11;
  62. buf[24]=0x76;
  63. buf[25]=0x4f;
  64. buf[26]=0xc0;
  65. buf[27]=0xa8;
  66. buf[28]=0x03;
  67. buf[29]=0xd1;
  68. buf[30]=0xff;
  69. buf[31]=0xff;
  70. buf[32]=0xff;
  71. buf[33]=0xff;
  72. buf[34]=0x9e;
  73. buf[35]=0xae;
  74. buf[36]=0x1a;
  75. buf[37]=0x0a;
  76. buf[38]=0x00;
  77. buf[39]=0x11;
  78. buf[40]=0x78;
  79. buf[41]=0xc5;
  80. buf[42]=0x31;
  81. buf[43]=0x32;
  82. buf[44]=0x33;
  83. buf[45]=0x34;
  84. buf[46]=0x35;
  85. buf[47]=0x36;
  86. buf[48]=0x37;
  87. buf[49]=0x38;
  88. buf[50]=0x39;
  89. int ii=0;
  90. while(1){
  91. ret=sendto(fd,buf,51,0,(struct sockaddr *)&dest,destlen);   //将构造的UDP帧发送到数据链路层
  92. if(ret<0){
  93. perror("error");
  94. }
  95. printf("%d\n",ii);
  96. ii++;
  97. sleep(1);
  98. }
  99. close(fd);
  100. printf("finished!\n");
  101. return 0;
  102. }

运行截图:

UDP发送端

UDP接收端

【3】Linux C UDP构造参考程序二

[cpp]  view plain copy
  1. /*  Copyright (C) 2011-2013  P.D. Buchan (pdbuchan@yahoo.com)
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. // Send an IPv4 UDP packet via raw socket at the link layer (ethernet frame).
  14. // Need to have destination MAC address.
  15. // Includes some UDP data.
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <unistd.h>           // close()
  19. #include <string.h>           // strcpy, memset(), and memcpy()
  20. #include <netdb.h>            // struct addrinfo
  21. #include <sys/types.h>        // needed for socket(), uint8_t, uint16_t, uint32_t
  22. #include <sys/socket.h>       // needed for socket()
  23. #include <netinet/in.h>       // IPPROTO_UDP, INET_ADDRSTRLEN
  24. #include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
  25. #include <netinet/udp.h>      // struct udphdr
  26. #include <arpa/inet.h>        // inet_pton() and inet_ntop()
  27. #include <sys/ioctl.h>        // macro ioctl is defined
  28. #include <bits/ioctls.h>      // defines values for argument "request" of ioctl.
  29. #include <net/if.h>           // struct ifreq
  30. #include <linux/if_ether.h>   // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD
  31. #include <linux/if_packet.h>  // struct sockaddr_ll (see man 7 packet)
  32. #include <net/ethernet.h>
  33. #include <errno.h>            // errno, perror()
  34. // Define some constants.
  35. #define ETH_HDRLEN 14  // Ethernet header length
  36. #define IP4_HDRLEN 20  // IPv4 header length
  37. #define UDP_HDRLEN  8  // UDP header length, excludes data
  38. #define SEV_PORT 6666
  39. // Function prototypes
  40. uint16_t checksum (uint16_t *, int);
  41. uint16_t udp4_checksum (struct ip, struct udphdr, uint8_t *, int);
  42. char *allocate_strmem (int);
  43. uint8_t *allocate_ustrmem (int);
  44. int *allocate_intmem (int);
  45. int
  46. main (int argc, char **argv)
  47. {
  48. int temp_i=0;
  49. for(temp_i=0;temp_i<40;temp_i++)
  50. {
  51. int i, status, datalen, frame_length, sd, bytes, *ip_flags; char *interface, *target, *src_ip, *dst_ip;
  52. struct ip iphdr;
  53. struct udphdr udphdr;
  54. uint8_t *data, *src_mac, *dst_mac, *ether_frame;
  55. struct addrinfo hints, *res;
  56. struct sockaddr_in *ipv4;
  57. struct sockaddr_ll device;
  58. struct ifreq ifr;
  59. void *tmp;
  60. // Allocate memory for various arrays.
  61. src_mac = allocate_ustrmem (6);
  62. dst_mac = allocate_ustrmem (6);
  63. data = allocate_ustrmem (IP_MAXPACKET);
  64. ether_frame = allocate_ustrmem (IP_MAXPACKET);
  65. interface = allocate_strmem (40);
  66. target = allocate_strmem (40);
  67. src_ip = allocate_strmem (INET_ADDRSTRLEN);
  68. dst_ip = allocate_strmem (INET_ADDRSTRLEN);
  69. ip_flags = allocate_intmem (4);
  70. // Interface to send packet through.
  71. strcpy (interface, "eth0");
  72. // Submit request for a socket descriptor to look up interface.
  73. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
  74. perror ("socket() failed to get socket descriptor for using ioctl() ");
  75. exit (EXIT_FAILURE);
  76. }
  77. // Use ioctl() to look up interface name and get its MAC address.
  78. memset (&ifr, 0, sizeof (ifr));
  79. snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  80. if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
  81. perror ("ioctl() failed to get source MAC address ");
  82. return (EXIT_FAILURE);
  83. }
  84. close (sd);
  85. // Copy source MAC address.
  86. memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));
  87. // Report source MAC address to stdout.
  88. printf ("MAC address for interface %s is ", interface);
  89. for (i=0; i<5; i++) {
  90. printf ("%02x:", src_mac[i]);
  91. }
  92. printf ("%02x\n", src_mac[5]);
  93. // Find interface index from interface name and store index in
  94. // struct sockaddr_ll device, which will be used as an argument of sendto().
  95. memset (&device, 0, sizeof (device));
  96. if ((device.sll_ifindex = if_nametoindex (interface)) == 0) {
  97. perror ("if_nametoindex() failed to obtain interface index ");
  98. exit (EXIT_FAILURE);
  99. }
  100. printf ("Index for interface %s is %i\n", interface, device.sll_ifindex);
  101. // Set destination MAC address: you need to fill these out
  102. dst_mac[0] = 0xff;
  103. dst_mac[1] = 0xff;
  104. dst_mac[2] = 0xff;
  105. dst_mac[3] = 0xff;
  106. dst_mac[4] = 0xff;
  107. dst_mac[5] = 0xff;
  108. // Source IPv4 address: you need to fill this out
  109. strcpy (src_ip, "192.168.3.209");
  110. // Destination URL or IPv4 address: you need to fill this out
  111. strcpy (target, "255.255.255.255");
  112. // Fill out hints for getaddrinfo().
  113. memset (&hints, 0, sizeof (struct addrinfo));
  114. hints.ai_family = AF_INET;
  115. hints.ai_socktype = SOCK_STREAM;
  116. hints.ai_flags = hints.ai_flags | AI_CANONNAME;
  117. // Resolve target using getaddrinfo().
  118. if ((status = getaddrinfo (target, NULL, &hints, &res)) != 0) {
  119. fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (status));
  120. exit (EXIT_FAILURE);
  121. }
  122. ipv4 = (struct sockaddr_in *) res->ai_addr;
  123. tmp = &(ipv4->sin_addr);
  124. if (inet_ntop (AF_INET, tmp, dst_ip, INET_ADDRSTRLEN) == NULL) {
  125. status = errno;
  126. fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status));
  127. exit (EXIT_FAILURE);
  128. }
  129. freeaddrinfo (res);
  130. // Fill out sockaddr_ll.
  131. device.sll_family = AF_PACKET;
  132. memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t));
  133. device.sll_halen = htons (6);
  134. // UDP data
  135. datalen = 9;
  136. data[0] = '1';
  137. data[1] = '2';
  138. data[2] = '3';
  139. data[3] = '4';
  140. data[4] = '5';
  141. data[5] = '6';
  142. data[6] = '7';
  143. data[7] = '8';
  144. data[8] = '9';
  145. // IPv4 header
  146. // IPv4 header length (4 bits): Number of 32-bit words in header = 5
  147. iphdr.ip_hl = IP4_HDRLEN / sizeof (uint32_t);
  148. // Internet Protocol version (4 bits): IPv4
  149. iphdr.ip_v = 4;
  150. // Type of service (8 bits)
  151. iphdr.ip_tos = 0;
  152. // Total length of datagram (16 bits): IP header + UDP header + datalen
  153. iphdr.ip_len = htons (IP4_HDRLEN + UDP_HDRLEN + datalen);
  154. // ID sequence number (16 bits): unused, since single datagram
  155. //iphdr.ip_id = htons (0x2e20+temp_i);
  156. iphdr.ip_id = htons(0);   //the ip_id can be constant or variable
  157. // Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram
  158. // Zero (1 bit)
  159. ip_flags[0] = 0;
  160. // Do not fragment flag (1 bit)
  161. ip_flags[1] = 1;
  162. // More fragments following flag (1 bit)
  163. ip_flags[2] = 0;
  164. // Fragmentation offset (13 bits)
  165. ip_flags[3] = 0;
  166. iphdr.ip_off = htons ((ip_flags[0] << 15)
  167. + (ip_flags[1] << 14)
  168. + (ip_flags[2] << 13)
  169. +  ip_flags[3]);
  170. // Time-to-Live (8 bits): default to maximum value
  171. iphdr.ip_ttl = 64;
  172. // Transport layer protocol (8 bits): 17 for UDP
  173. iphdr.ip_p = IPPROTO_UDP;
  174. // Source IPv4 address (32 bits)
  175. if ((status = inet_pton (AF_INET, src_ip, &(iphdr.ip_src))) != 1) {
  176. fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
  177. exit (EXIT_FAILURE);
  178. }
  179. // Destination IPv4 address (32 bits)
  180. if ((status = inet_pton (AF_INET, dst_ip, &(iphdr.ip_dst))) != 1) {
  181. fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
  182. exit (EXIT_FAILURE);
  183. }
  184. // IPv4 header checksum (16 bits): set to 0 when calculating checksum
  185. iphdr.ip_sum = 0;
  186. iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN);
  187. // UDP header
  188. // Source port number (16 bits): pick a number
  189. udphdr.source = htons (40622);
  190. // Destination port number (16 bits): pick a number
  191. udphdr.dest = htons (SEV_PORT);
  192. // Length of UDP datagram (16 bits): UDP header + UDP data
  193. udphdr.len = htons (UDP_HDRLEN + datalen);
  194. // UDP checksum (16 bits)
  195. udphdr.check = udp4_checksum (iphdr, udphdr, data, datalen);
  196. // Fill out ethernet frame header.
  197. // Ethernet frame length = ethernet header (MAC + MAC + ethernet type) + ethernet data (IP header + UDP header + UDP data)
  198. frame_length = 6 + 6 + 2 + IP4_HDRLEN + UDP_HDRLEN + datalen;
  199. // Destination and Source MAC addresses
  200. memcpy (ether_frame, dst_mac, 6 * sizeof (uint8_t));
  201. memcpy (ether_frame + 6, src_mac, 6 * sizeof (uint8_t));
  202. // Next is ethernet type code (ETH_P_IP for IPv4).
  203. // http://www.iana.org/assignments/ethernet-numbers
  204. ether_frame[12] = ETH_P_IP / 256;
  205. ether_frame[13] = ETH_P_IP % 256;
  206. // Next is ethernet frame data (IPv4 header + UDP header + UDP data).
  207. // IPv4 header
  208. memcpy (ether_frame + ETH_HDRLEN, &iphdr, IP4_HDRLEN * sizeof (uint8_t));
  209. // UDP header
  210. memcpy (ether_frame + ETH_HDRLEN + IP4_HDRLEN, &udphdr, UDP_HDRLEN * sizeof (uint8_t));
  211. // UDP data
  212. memcpy (ether_frame + ETH_HDRLEN + IP4_HDRLEN + UDP_HDRLEN, data, datalen * sizeof (uint8_t));
  213. // Submit request for a raw socket descriptor.
  214. if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
  215. perror ("socket() failed ");
  216. exit (EXIT_FAILURE);
  217. }
  218. // Send ethernet frame to socket.
  219. if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) {
  220. perror ("sendto() failed");
  221. exit (EXIT_FAILURE);
  222. }
  223. // Close socket descriptor.
  224. close (sd);
  225. // Free allocated memory.
  226. free (src_mac);
  227. free (dst_mac);
  228. free (data);
  229. free (ether_frame);
  230. free (interface);
  231. free (target);
  232. free (src_ip);
  233. free (dst_ip);
  234. free (ip_flags);
  235. sleep(1);
  236. printf("%d\n",temp_i);
  237. }
  238. return (EXIT_SUCCESS);
  239. }
  240. // Checksum function
  241. uint16_t
  242. checksum (uint16_t *addr, int len)
  243. {
  244. int nleft = len;
  245. int sum = 0;
  246. uint16_t *w = addr;
  247. uint16_t answer = 0;
  248. while (nleft > 1) {
  249. sum += *w++;
  250. nleft -= sizeof (uint16_t);
  251. }
  252. if (nleft == 1) {
  253. *(uint8_t *) (&answer) = *(uint8_t *) w;
  254. sum += answer;
  255. }
  256. sum = (sum >> 16) + (sum & 0xFFFF);
  257. sum += (sum >> 16);
  258. answer = ~sum;
  259. return (answer);
  260. }
  261. // Build IPv4 UDP pseudo-header and call checksum function.
  262. uint16_t
  263. udp4_checksum (struct ip iphdr, struct udphdr udphdr, uint8_t *payload, int payloadlen)
  264. {
  265. char buf[IP_MAXPACKET];
  266. char *ptr;
  267. int chksumlen = 0;
  268. int i;
  269. ptr = &buf[0];  // ptr points to beginning of buffer buf
  270. // Copy source IP address into buf (32 bits)
  271. memcpy (ptr, &iphdr.ip_src.s_addr, sizeof (iphdr.ip_src.s_addr));
  272. ptr += sizeof (iphdr.ip_src.s_addr);
  273. chksumlen += sizeof (iphdr.ip_src.s_addr);
  274. // Copy destination IP address into buf (32 bits)
  275. memcpy (ptr, &iphdr.ip_dst.s_addr, sizeof (iphdr.ip_dst.s_addr));
  276. ptr += sizeof (iphdr.ip_dst.s_addr);
  277. chksumlen += sizeof (iphdr.ip_dst.s_addr);
  278. // Copy zero field to buf (8 bits)
  279. *ptr = 0; ptr++;
  280. chksumlen += 1;
  281. // Copy transport layer protocol to buf (8 bits)
  282. memcpy (ptr, &iphdr.ip_p, sizeof (iphdr.ip_p));
  283. ptr += sizeof (iphdr.ip_p);
  284. chksumlen += sizeof (iphdr.ip_p);
  285. // Copy UDP length to buf (16 bits)
  286. memcpy (ptr, &udphdr.len, sizeof (udphdr.len));
  287. ptr += sizeof (udphdr.len);
  288. chksumlen += sizeof (udphdr.len);
  289. // Copy UDP source port to buf (16 bits)
  290. memcpy (ptr, &udphdr.source, sizeof (udphdr.source));
  291. ptr += sizeof (udphdr.source);
  292. chksumlen += sizeof (udphdr.source);
  293. // Copy UDP destination port to buf (16 bits)
  294. memcpy (ptr, &udphdr.dest, sizeof (udphdr.dest));
  295. ptr += sizeof (udphdr.dest);
  296. chksumlen += sizeof (udphdr.dest);
  297. // Copy UDP length again to buf (16 bits)
  298. memcpy (ptr, &udphdr.len, sizeof (udphdr.len));
  299. ptr += sizeof (udphdr.len);
  300. chksumlen += sizeof (udphdr.len);
  301. // Copy UDP checksum to buf (16 bits)
  302. // Zero, since we don't know it yet
  303. *ptr = 0; ptr++;
  304. *ptr = 0; ptr++;
  305. chksumlen += 2;
  306. // Copy payload to buf
  307. memcpy (ptr, payload, payloadlen);
  308. ptr += payloadlen;
  309. chksumlen += payloadlen;
  310. // Pad to the next 16-bit boundary
  311. for (i=0; i<payloadlen%2; i++, ptr++) {
  312. *ptr = 0;
  313. ptr++;
  314. chksumlen++;
  315. }
  316. return checksum ((uint16_t *) buf, chksumlen);
  317. }
  318. // Allocate memory for an array of chars.
  319. char *
  320. allocate_strmem (int len)
  321. {
  322. void *tmp;
  323. if (len <= 0) {
  324. fprintf (stderr, "ERROR: Cannot allocate memory because len = %i in allocate_strmem().\n", len);
  325. exit (EXIT_FAILURE);
  326. }
  327. tmp = (char *) malloc (len * sizeof (char));
  328. if (tmp != NULL) {
  329. memset (tmp, 0, len * sizeof (char));
  330. return (tmp);
  331. } else {
  332. fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_strmem().\n");
  333. exit (EXIT_FAILURE);
  334. }
  335. }
  336. // Allocate memory for an array of unsigned chars.
  337. uint8_t *
  338. allocate_ustrmem (int len)
  339. {
  340. void *tmp;
  341. if (len <= 0) {
  342. fprintf (stderr, "ERROR: Cannot allocate memory because len = %i in allocate_ustrmem().\n", len);
  343. exit (EXIT_FAILURE);
  344. }
  345. tmp = (uint8_t *) malloc (len * sizeof (uint8_t));
  346. if (tmp != NULL) {
  347. memset (tmp, 0, len * sizeof (uint8_t));
  348. return (tmp);
  349. } else {
  350. fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_ustrmem().\n");
  351. exit (EXIT_FAILURE);
  352. }
  353. }
  354. // Allocate memory for an array of ints.
  355. int *
  356. allocate_intmem (int len)
  357. {
  358. void *tmp;
  359. if (len <= 0) {
  360. fprintf (stderr, "ERROR: Cannot allocate memory because len = %i in allocate_intmem().\n", len);
  361. exit (EXIT_FAILURE);
  362. }
  363. tmp = (int *) malloc (len * sizeof (int));
  364. if (tmp != NULL) {
  365. memset (tmp, 0, len * sizeof (int));
  366. return (tmp);
  367. } else {
  368. fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_intmem().\n");
  369. exit (EXIT_FAILURE);
  370. }
  371. }

运行效果:

UDP发送端

UDP接收端

所有有参考价值的程序都在上面了,当然还有很多不明白的地方,一时搞不明白,以后遇到了再深入研究吧。

Linux下使用RAW SOCKET原始套接字构造UDP原始数据帧广播到局域网,在局域网的另一台计算机上显示UDP发送的信息相关推荐

  1. linux网络编程Internet Socket地址,套接字,和函数

    文章内容节选<linux/UNIX 系统网络编程> Internet domain socket地址有两种:IPv4 IPv6 IPv4被存储在结构体中, 该结构体在 netinet/in ...

  2. java原始套接字,raw socket介绍(示例代码)

    原文: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=876233 test 1.原始套接字(raw socket) 1.1 原始 ...

  3. Linux原始套接字学习总结

    Linux网络编程:原始套接字的魔力[上] http://blog.chinaunix.net/uid-23069658-id-3280895.html 基于原始套接字编程        在开发面向连 ...

  4. Linux原始套接字实现分析---转

    http://blog.chinaunix.net/uid-27074062-id-3388166.html 本文从IPV4协议栈原始套接字的分类入手,详细介绍了链路层和网络层原始套接字的特点及其内核 ...

  5. linux 原始套接字 绑定网卡,Linux原始套接字实现分析

    之所以要转这篇文章,是因为这篇文章是我看到的同类博客中写得最好的,但非常可惜,这篇博客中只有一篇文章,没有什么收藏价值,故将其原文转载,以供今后学习查阅. 本文从IPV4协议栈原始套接字的分类入手,详 ...

  6. linux 原始套接字实现分析

    目录 1 原始套接字概述 1.1 链路层原始套接字 1.2 网络层原始套接字 1.2.1 接收报文 1.2.2 发送报文 2 原始套接字实现 2.1 原始套接字报文收发流程 2.2  链路层原始套接字 ...

  7. 【Linux网络编程】原始套接字能干什么?

    通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...

  8. Linux网络编程——原始套接字能干什么?

    一.知识回顾: 通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式 ...

  9. Raw_Socket原始套接字

    一.创建raw socket的权限:只有root权限才能够创建. 二.raw socket的用途:主要有三个方面 (1):通过raw socket来接收发向本机的ICMP,IGMP协议包,或者用来发送 ...

最新文章

  1. Nature子刊:用16S及18S rRNA全长进行微生物多样性研究
  2. [HOW TO]-下载android官方源码
  3. 司机和售票员问题 信号signal注册一例
  4. JS中数据类型、内置对象、包装类型对象、typeof关系
  5. 详解三种主流分布式事务方案的优劣
  6. python爬虫:其他操作
  7. 使用Mockito测试Spring组件
  8. 搜索引擎的十大秘密(收藏)
  9. 用批处理读取特定注册表项的路径值
  10. 防止android应用的内存泄露
  11. myeclipse 8.6安装freemarker插件
  12. 金融反欺诈 常用特征处理方法
  13. C# 通过Http获取网页内容
  14. 硬盘数据恢复原理与方法
  15. JavaScript经典pdf书籍推荐
  16. NOIP 考后欢乐赛 T2 中国象棋
  17. 前端生成海报的 N 种方案和优劣对比
  18. Redis 开机自启
  19. Ubuntu16.04搭建ftp/tftp/nfs/ssh服务器
  20. Vue2---全局事件总线

热门文章

  1. [plugin:vite:import-analysis]Failed to resolve import “@/“ from ““.Does the file exist
  2. 手把手教你,嘴对嘴传达------Apache(安全优化防盗链、隐藏版本信息)
  3. 二叉搜索树的JAVA实现-201805
  4. HTTP上传文件的总结
  5. php屏蔽地区_屏蔽指定省份访问PHP代码
  6. 求数组中的最大值和次大值
  7. 在线分享 Hosts 规则工具:Remote Hosts Server
  8. 一览Polkadot平行链Moonbeam生态的应用
  9. 我和小伙伴们一起学Unity3D(六)碰撞与触发器
  10. 实战:react16+CRA