linux原始套接字(4)-構造IP_UDP

来源:http://www.cnblogs.com/yuuyuu/archive/2016/01/29/5170056.html
-Advertisement-
Play Games

一.概述 同上一篇tcp一樣,udp也是封裝在ip報文裡面。創建UDP的原始套接字如下: 1 (sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); 同樣,如果要構造udp的ip首部,要開啟IP_HDRINCL選項! udp首部格式: udp的不可靠性,比


一.概述                                                   

上一篇tcp一樣,udp也是封裝在ip報文裡面。創建UDP的原始套接字如下:

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

同樣,如果要構造udp的ip首部,要開啟IP_HDRINCL選項!

udp首部格式:

udp的不可靠性,比tcp報文簡單很多。上面的16位UDP長度是UDP首部+普通數據的總長度,這點跟ip首部的16位總長度一樣!

udp結構定義在netinet/udp.h

 1 struct udphdr
 2 {
 3   __extension__ union
 4   {
 5     struct
 6     {
 7       u_int16_t uh_sport;        /* source port */
 8       u_int16_t uh_dport;        /* destination port */
 9       u_int16_t uh_ulen;        /* udp length */
10       u_int16_t uh_sum;        /* udp checksum */
11     };
12     struct
13     {
14       u_int16_t source;
15       u_int16_t dest;
16       u_int16_t len;
17       u_int16_t check;
18     };
19   };
20 };

二.構造IP_UDP報文發送                       

  1 /**
  2  * @file ip_udp_send.c
  3  */
  4 
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 #include <string.h>
  8 #include <unistd.h>
  9 #include <sys/socket.h>
 10 #include <arpa/inet.h>
 11 #include <netinet/ip.h>
 12 #include <netinet/udp.h>
 13 
 14 /* ip首部長度 */
 15 #define IP_HEADER_LEN sizeof(struct ip)
 16 /* udp首部長度 */
 17 #define UDP_HEADER_LEN sizeof(struct udphdr)
 18 /* ip首部 + udp首部長度 */
 19 #define IP_UDP_HEADER_LEN IP_HEADER_LEN + UDP_HEADER_LEN
 20 
 21 void err_exit(const char *err_msg)
 22 {
 23     perror(err_msg);
 24     exit(1);
 25 }
 26 
 27 /* 填充ip首部 */
 28 struct ip *fill_ip_header(const char *src_ip, const char *dst_ip, int ip_packet_len)
 29 {
 30     struct ip *ip_header;
 31 
 32     ip_header = (struct ip *)malloc(IP_HEADER_LEN);
 33     ip_header->ip_v = IPVERSION;
 34     ip_header->ip_hl = IP_HEADER_LEN / 4;
 35     ip_header->ip_tos = 0;
 36     ip_header->ip_len = htons(ip_packet_len);
 37     ip_header->ip_id = 0;
 38     ip_header->ip_off = 0;
 39     ip_header->ip_ttl = MAXTTL;
 40     ip_header->ip_p = IPPROTO_UDP;        /* 這裡是UDP */
 41     ip_header->ip_sum = 0;
 42     ip_header->ip_src.s_addr = inet_addr(src_ip);
 43     ip_header->ip_dst.s_addr = inet_addr(dst_ip);
 44 
 45     return ip_header;
 46 }
 47 
 48 /* 填充udp首部 */
 49 struct udphdr *fill_udp_header(int src_port, int dst_port, int udp_packet_len)
 50 {
 51     struct udphdr *udp_header;
 52 
 53     udp_header = (struct udphdr *)malloc(UDP_HEADER_LEN);
 54     udp_header->source = htons(src_port);
 55     udp_header->source = htons(dst_port);
 56     /* 這裡的長度是整個UDP報文 */
 57     udp_header->len = htons(udp_packet_len);
 58     udp_header->check = 0;
 59 
 60     return udp_header;
 61 }
 62 
 63 /* 發送ip_udp報文 */
 64 void ip_udp_send(const char *src_ip, int src_port, const char *dst_ip, int dst_port, const char *data)
 65 {
 66     struct ip *ip_header;
 67     struct udphdr *udp_header;
 68     struct sockaddr_in dst_addr;
 69     socklen_t sock_addrlen = sizeof(struct sockaddr_in);
 70 
 71     int data_len = strlen(data);
 72     int ip_packet_len = IP_UDP_HEADER_LEN + data_len;
 73     int udp_packet_len = UDP_HEADER_LEN + data_len;
 74     char buf[ip_packet_len];
 75     int sockfd, ret_len, on = 1;
 76 
 77     bzero(&dst_addr, sock_addrlen);
 78     dst_addr.sin_family = PF_INET;
 79     dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
 80     dst_addr.sin_port = htons(dst_port);
 81 
 82     /* 創建udp原始套接字 */
 83     if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
 84         err_exit("socket()");
 85 
 86     /* 開啟IP_HDRINCL,自定義IP首部 */
 87     if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
 88         err_exit("setsockopt()");
 89 
 90     /* ip首部 */
 91     ip_header = fill_ip_header(src_ip, dst_ip, ip_packet_len);
 92     /* udp首部 */
 93     udp_header = fill_udp_header(src_port, dst_port, udp_packet_len);
 94 
 95     bzero(buf, ip_packet_len);
 96     memcpy(buf, ip_header, IP_HEADER_LEN);
 97     memcpy(buf + IP_HEADER_LEN, udp_header, UDP_HEADER_LEN);
 98     memcpy(buf + IP_UDP_HEADER_LEN, data, data_len);
 99 
100     /* 發送報文 */
101     ret_len = sendto(sockfd, buf, ip_packet_len, 0, (struct sockaddr *)&dst_addr, sock_addrlen);
102     if (ret_len > 0)
103         printf("sendto() ok!!!\n");
104     else printf("sendto() failed\n");
105 
106     close(sockfd);
107     free(ip_header);
108     free(udp_header);
109 }
110 
111 int main(int argc, const char *argv[])
112 {
113     if (argc != 6)
114     {
115         printf("usage:%s src_ip src_port dst_ip dst_port data\n", argv[0]);
116         exit(1);
117     }
118 
119     /* 發送ip_udp報文 */
120     ip_udp_send(argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), argv[5]);
121 
122     return 0;
123 }

上面的大部分代碼都跟上一篇差不多。不同的是這次是填充udp首部,創建原始套接字的類型是UDP。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 解決:Host xxx.xxx.xxx.xxx is blocked because of many connection errors.
  • 1、假設備份文件xxxx.bak大小約300G,還原後所占用的空間為900G 2、磁碟空間只有1T,若將備份文件拷貝過來,空間剩餘700G,無法成功還原,因此通過遠程方式還原。 例子如下: SQLSERVER服務實例名稱: 192.168.12.163需要備份的資料庫名稱: a備份機器名稱(Clie
  • 配置文件內容:[root@yoon etc]# cat mongod.conf logpath=/export/log/mongodb.loglogappend=truefork = truedbpath=/export/data/dbpidfilepath = /export/mongodb/et
  • ===================================================================================================================#!/bin/sh. /etc/profile DATE=`date
  • Output子句日常灰常有用,而且用的地方也挺多,但是確好多時候被我們忽視,今天我就也簡單掃盲一下這個語句的用法。 Output子句 返回受 INSERT、UPDATE、DELETE 或 MERGE 語句影響的各行中的信息,或返回基於受這些語句影響的各行的表達式。 這些結果可以返回到處理應用程式,以
  • 一直沒有在意過資料庫處理樹形數據的重要性,直到有一天朋友問起我關於樹形數據查詢的問題時才發現根本不會,正好這個時候也要用到遞歸進行樹形數據的查詢於是在網上查了一圈,語法總結如下 參考文獻:https://msdn.microsoft.com/query/dev10.query?appId=Dev10
  • declare @temp_temp uniqueidentifier--臨時變數 DECLARE aaa CURSOR for select Id from A -------------------打開游標 open aaa --先查詢一次再迴圈,防止有多個游標時@@FETCH_STATUS=-
  • 目錄 1 建立資料庫檔案 2 在sqlite3提示列下操作 3 SQL的指令格式 4 建立資料表 5 建立索引 6 加入一筆資料 7 查詢資料 8 如何更改或刪除資料 9 其他sqlite的特別用法 10 小結 建立資料庫檔案 用sqlite3建立資料庫的方法很簡單,只要在shell下鍵入(以下$符
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...