码迷,mamicode.com
首页 > 其他好文 > 详细

004.原始套接字,拼接UDP数据包,通信

时间:2015-11-19 22:26:47      阅读:378      评论:0      收藏:0      [点我收藏+]

标签:

大致流程:

    建立一个client端,一个server端,自己构建IP头和UDP头,写入数据(hello,world!)后通过原始套接字(SOCK_RAW)将包发出去。

server端收到数据后,打印UDP数据并发送确认消息(yes),client收到yes后将其打印。

其中:

client端IP:192.168.11.104 端口:8600

server端IP:192.168.11.105 端口:8686

注意事项:

1.运行原始套接字socket需要有root权限。

2.注意主机字节序和网络字节序的

实现如下:

client端:

 

  1 /*
  2  ============================================================================
  3  Name        : test_client.c
  4  Author      : huh
  5  Version     :
  6  Copyright   : ---notice---
  7  Description : Hello World in C, Ansi-style
  8  ============================================================================
  9  */
 10 
 11 #include <sys/types.h>
 12 #include <sys/socket.h>
 13 #include <stdio.h>
 14 #include <netinet/in.h>
 15 #include <arpa/inet.h>
 16 #include <unistd.h>
 17 #include <stdlib.h>
 18 #include <string.h>
 19 #include <netinet/ip_icmp.h>
 20 #include <netinet/udp.h>
 21 
 22 #define MAXLINE 1024*10
 23 
 24 struct udp_front  //udp
 25 {
 26     uint32_t srcip;
 27     uint32_t desip;
 28     u_int8_t zero;
 29     u_int8_t protocol;
 30     u_int16_t len;
 31 };
 32 
 33 u_int16_t in_chksum(u_int16_t *addr, int len);
 34 u_int16_t udp_check(char *sendbuf, int len, const struct udp_front front);
 35 int make_message(char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port);
 36 
 37 int main()
 38 {
 39     int raw_sockfd;
 40     int size = 1024*50;
 41     char send_message[MAXLINE];
 42     struct sockaddr_in server_address;
 43     //创建原始套接字
 44     raw_sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
 45     //创建套接字地址
 46     bzero(&server_address,sizeof(server_address));
 47     server_address.sin_family = AF_INET;
 48     server_address.sin_addr.s_addr = inet_addr("192.168.11.105");
 49     //设置套接字为随数据包含IP首部(设置这个选项后需要我们手动写入IP头)
 50     setsockopt(raw_sockfd, IPPROTO_IP, IP_HDRINCL, &size, sizeof(size));
 51 
 52     int len;
 53     bzero(&send_message, sizeof(send_message));
 54     //拼接完整的UDP数据包(IP头+UDP头+数据)
 55     int mesg_len = make_message(send_message, MAXLINE, inet_addr("192.168.11.104"), 8600, inet_addr("192.168.11.105"), 8686);
 56     //将IP数据包发送出去
 57     sendto(raw_sockfd, send_message, mesg_len, 0, (struct sockaddr *)&server_address, sizeof(server_address));
 58     close(raw_sockfd);
 59     //
 60     //下面我们开始接受服务器返回的包
 61     int client_sockfd;
 62     int server_len;
 63     char recv_message[MAXLINE];
 64     struct sockaddr_in server_addr;
 65     client_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 66     server_addr.sin_family = AF_INET;
 67     server_addr.sin_addr.s_addr = inet_addr("192.168.11.104");
 68     server_addr.sin_port = htons(8600);
 69     server_len = sizeof(server_address);
 70     bind(client_sockfd, (struct sockaddr *)&server_addr, server_len);
 71 
 72     bzero(&recv_message, sizeof(recv_message));
 73        len = recvfrom(client_sockfd, recv_message, MAXLINE, 0, NULL, NULL);
 74        printf("收到的应答:%s\n",recv_message);
 75     return 0;
 76 }
 77 
 78 //拼接IP数据报
 79 int make_message(char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port)
 80 {
 81     char message[1005];
 82     bzero(message, sizeof(message));
 83     strcpy(message,"hello,world!");
 84     printf("message len:%d\n",strlen(message));
 85     struct iphdr *ip;
 86     ip = (struct iphdr *)sendbuf;
 87     ip->ihl = sizeof(struct iphdr) >> 2; //首部长度
 88     ip->version = 4;   //ip协议版本
 89     ip->tos = 0;   //服务类型字段
 90     ip->tot_len = 0;   //总长度
 91     ip->id = 1000;   //
 92     ip->frag_off = 0;
 93     ip->ttl = 128;
 94     ip->protocol = IPPROTO_UDP;
 95     ip->check = 0;  //内核会算相应的效验和
 96     ip->saddr = src_ip;
 97     ip->daddr = des_ip;
 98 
 99     struct udp_front front;
100     front.srcip = src_ip;
101     front.desip = des_ip;
102     front.len = htons(8+strlen(message));
103     front.protocol = 17;
104     front.zero = 0;
105 
106     struct udphdr *udp;
107     udp = (struct udphdr *)(sendbuf + sizeof(struct iphdr));
108     udp->source = htons(src_port);  //源端口
109     udp->dest = htons(des_port);    //目的端口
110     udp->check = 0;   //效验和,效验整个udp数据报
111     strcpy((sendbuf+20+8), message);
112     udp->len = htons(8+strlen(message)); //udp数据报总长度
113 
114     udp->check = udp_check((sendbuf+20), 8+strlen(message), front);
115 
116     ip->tot_len = (20 + 8 + strlen(message));   //总长度
117     printf("ip->tot_len:%d\n",ip->tot_len);
118     ip->check = in_chksum((unsigned short *)sendbuf, 20);
119 
120     return (ip->tot_len);
121 }
122 
123 //计算udp效验和
124 unsigned short udp_check(char *sendbuf, int len, const struct udp_front front)
125 {
126     char str[MAXLINE];
127     bzero(&str, MAXLINE);
128     bcopy(&front, str, sizeof(front));
129     bcopy(sendbuf, str+sizeof(front), len);
130     struct udp_front *ptr;
131     ptr = (struct udp_front *)str;
132     char *s;
133     s = (str+20);
134     return in_chksum((unsigned short *)str, sizeof(front)+len);
135 }
136 
137 //效验和算法
138 uint16_t in_chksum(uint16_t *addr, int len)
139 {
140     int nleft = len;
141     uint32_t sum = 0;
142     uint16_t *w = addr;
143     uint16_t answer = 0;
144     //把ICMP报头二进制数据以2字节为单位累加起来
145     while (nleft > 1)
146     {
147         sum += *w++;
148         nleft -= 2;
149     }
150     if (nleft == 1)
151     {
152         *(unsigned char *)(&answer) = *(unsigned char *)w;
153         sum += answer;
154     }
155     sum = (sum>>16) + (sum&0xffff);
156     sum += (sum>>16);
157     answer = ~sum;
158     return answer;
159 }

 

 

 

 

server端:

 1 /*
 2  ============================================================================
 3  Name        : test_server.c
 4  Author      : huh
 5  Version     :
 6  Copyright   : ---notice---
 7  Description : Hello World in C, Ansi-style
 8  ============================================================================
 9  */
10 
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <stdio.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #define MAXLINE 1024*50
21 
22 int main()
23 {
24     int server_sockfd;
25     int server_len, client_len;
26     struct sockaddr_in server_address;
27     struct sockaddr_in client_address;
28 
29     server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
30 
31     server_address.sin_family = AF_INET;
32     server_address.sin_addr.s_addr = inet_addr("192.168.11.105");
33     server_address.sin_port = htons(8686);
34 
35     server_len = sizeof(server_address);
36     bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
37 
38     for( ; ; )
39     {
40         int len;
41         char recv_mesg[MAXLINE];
42         char send_mesg[20];
43         client_len = sizeof(struct sockaddr_in);
44         printf("server2 waiting!\n");
45         len = recvfrom(server_sockfd, recv_mesg, MAXLINE, 0, (struct sockaddr *) &client_address, (socklen_t *) &client_len);
46         printf("收到包的长度为:%d\n",len);
47         printf("%s\n",recv_mesg);
48         strcpy(send_mesg,"yes");
49         sendto(server_sockfd, send_mesg, strlen(send_mesg), 0, (struct sockaddr *) &client_address, client_len);  //将包发出去
50         ;
51     }
52     return 0;
53 }

 

004.原始套接字,拼接UDP数据包,通信

标签:

原文地址:http://www.cnblogs.com/ruo-yu/p/4979020.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!