一.概述                                                   

同上一篇tcp一样,udp也是封装在ip报文里面。创建UDP的原始套接字如下:

 (sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);

同样,如果要构造udp的ip首部,要开启IP_HDRINCL选项!

udp首部格式:

udp的不可靠性,比tcp报文简单很多。上面的16位UDP长度是UDP首部+普通数据的总长度,这点跟ip首部的16位总长度一样!

udp结构定义在netinet/udp.h

 struct udphdr
 {
   __extension__ union
   {
     struct
     {
       u_int16_t uh_sport;        /* source port */
       u_int16_t uh_dport;        /* destination port */
       u_int16_t uh_ulen;        /* udp length */
       u_int16_t uh_sum;        /* udp checksum */
     };
     struct
     {
       u_int16_t source;
       u_int16_t dest;
       u_int16_t len;
       u_int16_t check;
     };
   };
 };

二.构造IP_UDP报文发送                       

 /**
  * @file ip_udp_send.c
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/udp.h>

 /* ip首部长度 */
 #define IP_HEADER_LEN sizeof(struct ip)
 /* udp首部长度 */
 #define UDP_HEADER_LEN sizeof(struct udphdr)
 /* ip首部 + udp首部长度 */
 #define IP_UDP_HEADER_LEN IP_HEADER_LEN + UDP_HEADER_LEN

 void err_exit(const char *err_msg)
 {
     perror(err_msg);
     exit();
 }

 /* 填充ip首部 */
 struct ip *fill_ip_header(const char *src_ip, const char *dst_ip, int ip_packet_len)
 {
     struct ip *ip_header;

     ip_header = (struct ip *)malloc(IP_HEADER_LEN);
     ip_header->ip_v = IPVERSION;
     ip_header->ip_hl = IP_HEADER_LEN / ;
     ip_header->ip_tos = ;
     ip_header->ip_len = htons(ip_packet_len);
     ip_header->ip_id = ;
     ip_header->ip_off = ;
     ip_header->ip_ttl = MAXTTL;
     ip_header->ip_p = IPPROTO_UDP;        /* 这里是UDP */
     ip_header->ip_sum = ;
     ip_header->ip_src.s_addr = inet_addr(src_ip);
     ip_header->ip_dst.s_addr = inet_addr(dst_ip);

     return ip_header;
 }

 /* 填充udp首部 */
 struct udphdr *fill_udp_header(int src_port, int dst_port, int udp_packet_len)
 {
     struct udphdr *udp_header;

     udp_header = (struct udphdr *)malloc(UDP_HEADER_LEN);
     udp_header->source = htons(src_port);
     udp_header->dest = htons(dst_port);
     /* 这里的长度是整个UDP报文 */
     udp_header->len = htons(udp_packet_len);
     udp_header->check = ;

     return udp_header;
 }

 /* 发送ip_udp报文 */
 void ip_udp_send(const char *src_ip, int src_port, const char *dst_ip, int dst_port, const char *data)
 {
     struct ip *ip_header;
     struct udphdr *udp_header;
     struct sockaddr_in dst_addr;
     socklen_t sock_addrlen = sizeof(struct sockaddr_in);

     int data_len = strlen(data);
     int ip_packet_len = IP_UDP_HEADER_LEN + data_len;
     int udp_packet_len = UDP_HEADER_LEN + data_len;
     char buf[ip_packet_len];
     ;

     bzero(&dst_addr, sock_addrlen);
     dst_addr.sin_family = PF_INET;
     dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
     dst_addr.sin_port = htons(dst_port);

     /* 创建udp原始套接字 */
     )
         err_exit("socket()");

     /* 开启IP_HDRINCL,自定义IP首部 */
     )
         err_exit("setsockopt()");

     /* ip首部 */
     ip_header = fill_ip_header(src_ip, dst_ip, ip_packet_len);
     /* udp首部 */
     udp_header = fill_udp_header(src_port, dst_port, udp_packet_len);

     bzero(buf, ip_packet_len);
     memcpy(buf, ip_header, IP_HEADER_LEN);
     memcpy(buf + IP_HEADER_LEN, udp_header, UDP_HEADER_LEN);
     memcpy(buf + IP_UDP_HEADER_LEN, data, data_len);

     /* 发送报文 */
     ret_len = sendto(sockfd, buf, ip_packet_len, , (struct sockaddr *)&dst_addr, sock_addrlen);
     )
         printf("sendto() ok!!!\n");
     else printf("sendto() failed\n");

     close(sockfd);
     free(ip_header);
     free(udp_header);
 }

 int main(int argc, const char *argv[])
 {
     )
     {
         printf(]);
         exit();
     }

     /* 发送ip_udp报文 */
     ip_udp_send(argv[], atoi(argv[]), argv[], atoi(argv[]), argv[]);

     ;
 }

上面的大部分代码都跟上一篇差不多。不同的是这次是填充udp首部,创建原始套接字的类型是UDP。

linux原始套接字(4)-构造IP_UDP的更多相关文章

  1. linux原始套接字(3)-构造IP_TCP发送与接收

    一.概述                                                    tcp报文封装在ip报文中,创建tcp的原始套接字如下: sockfd = socket ...

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

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

  3. Linux原始套接字抓取底层报文

    1.原始套接字使用场景 我们平常所用到的网络编程都是在应用层收发数据,每个程序只能收到发给自己的数据,即每个程序只能收到来自该程序绑定的端口的数据.收到的数据往往只包括应用层数据,原有的头部信息在传递 ...

  4. 关于linux 原始套接字编程

    关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...

  5. linux原始套接字(2)-icmp请求与接收

    一.概述                                                    上一篇arp请求使用的是链路层的原始套接字.icmp封装在ip数据报里面,所以icmp请 ...

  6. linux原始套接字(1)-arp请求与接收

    一.概述                                                   以太网的arp数据包结构: arp结构op操作参数:1为请求,2为应答. 常用的数据结构如 ...

  7. UNP——原始套接字

    1.原始套接字的用处 使用原始套接字可以构造或读取网际层及其以上报文. 具体来说,可以构造 ICMP, IGMP 协议报文,通过开启 IP_HDRINCL 套接字选项,进而自定义 IPv4首部. 2. ...

  8. Linux基础(11)原始套接字

    一边接收函数返回一边判断返回值时一定要把接收的优先级加()提高再去判断 例 if((sockfd = socket()) < 0) 问题: 如何实现SYN扫描器扫描端口 , 比如AB两个设备要进 ...

  9. Linux Socket 原始套接字编程

    对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...

随机推荐

  1. mybatis 3的TypeHandler解析(null值的处理)

    最近,在测试迁移公司的交易客户端连接到自主研发的中间件时,调用DAO层时,发现有些参数并没有传递,而在mapper里面是通过parameterMap传递的,因为有些参数为null,这就导致了参数传递到 ...

  2. 把GAE程序通过SSH部署到 VPS

    大部分在文档上都写了, 写这篇文章的目的是发现现在appcfg.py update xxxx的时候会打开浏览器访问google请求授权(后台内建了一个本地server, 端口是8090, 授权成功后会 ...

  3. 初探百度F.I.S — 由工具到解决方案

    1. 前言 阅兵放假三天,我哪儿也没去,宅着看了一些东东:git命令行.svn命令以及下面的主角——百度FIS.对看过的git.svn的命令也做了一些总结,请参见:<git命令学习笔记>和 ...

  4. Vue.js – 基于 MVVM 实现交互式的 Web 界面

    Vue.js 是用于构建交互式的 Web  界面的库.它提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单.灵活的 API.从技术上讲, Vue.js 集中在 MVVM 模式上的视图模型层,并 ...

  5. 经典!HTML5 Canvas 模拟可撕裂布料效果

    这是一个模拟可撕裂布料效果的 HTML5 Canvas 应用演示,效果逼真.你会看到,借助 Canvas 的强大绘图和动画功能,只需很少的代码就能实现让您屏息凝神的效果. 温馨提示:为保证最佳的效果, ...

  6. [deviceone开发]-基础文件管理器

    一.简介 主要实现本地文件管理功能,主要功能为复制.粘贴.剪切目录或者文件. 二.效果 三.相关下载 https://github.com/do-project/code4do/tree/master ...

  7. mongodb 数据库操作--备份 还原 导出 导入

    mongodb数据备份和还原主要分为二种,一种是针对于库的mongodump和mongorestore,一种是针对库中表的mongoexport和mongoimport 一,mongodump备份数据 ...

  8. Hosting socket.io WebSocket apps in IIS using iisnode

    In this post I explain how to configure a socket.io node.js application to use of WebSockets when ho ...

  9. Android Animation学习(四) ApiDemos解析:多属性动画

    Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...

  10. Android Handler机制(一)---Message源码分析

    Message: 定义: public final class Message implements Parcelable Message类是个final类,就是说不能被继承,同时Message类实现 ...