raw socket 编程实例

raw socket编程实例

1685人阅读 评论(0) 收藏 举报
分类:
网络编程(5)

由于最经做模拟TCP三次握手的实验,需要用到raw socket编程。

运行第一段代码,发送ip数据报,第二段代码接收ip数据报。需要运行第二段代码,否则将无法接收数据报。

  1. <span style="font-size:18px;">#include<stdio.h>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #include<sys/socket.h>  
  5. #include<sys/types.h>  
  6. #include<netinet/in.h>  
  7.   
  8. struct iphead{   //该结构体模拟IP首部(代码中,控制套接字不添加IP数据包首部,需要自己添加),</span>  
  1. <span style="font-size:18px;"><span style="white-space:pre;">       </span>//关于各变量的含义,可对照IP数据报格式,一目了然。  
  2.     unsigned char ip_hl:4, ip_version:4;  //ip_hl,ip_version各占四个bit位。  
  3.     unsigned char ip_tos;  
  4.     unsigned short int ip_len;     
  5.     unsigned short int ip_id;  
  6.     unsigned short int ip_off;    
  7.     unsigned char ip_ttl;  
  8.     unsigned char ip_pro;  
  9.     unsigned short int ip_sum;  
  10.     unsigned int ip_src;  
  11.     unsigned int ip_dst;  
  12. };  
  13.   
  14. struct icmphead{  //</span><span style="font-size:18px;font-family:Arial, Helvetica, sans-serif;">该结构体模拟ICMP报文首部</span><span style="font-size:18px;">  
  15.     unsigned char icmp_type;  
  16.     unsigned char icmp_code;  
  17.     unsigned short int icmp_sum;  
  18.     unsigned short int icmp_id;  
  19.     unsigned short int icmp_seq;  
  20. };  
  21.   
  22. unsigned short int cksum(char buffer[], int size){   //计算校验和,具体的算法可自行百度,或查阅资料  
  23.     unsigned long sum = 0;  
  24.     unsigned short int answer;  
  25.     unsigned short int *temp;  
  26.     temp = (short int *)buffer;  
  27.     for( ; temp<buffer+size; temp+=1){  
  28.         sum += *temp;  
  29.     }  
  30.     sum = (sum >> 16) + (sum & 0xffff);  
  31.     sum += (sum >> 16);  
  32.     answer = ~sum;  
  33.     return answer;  
  34. }  
  35.   
  36. int main(){  
  37.      
  38.     int sockfd;  
  39.     struct sockaddr_in conn;  
  40.     struct iphead *ip;  
  41.     struct icmphead *icmp;  
  42.     unsigned char package[sizeof(struct iphead) + sizeof(struct icmphead)];  //package存储IP数据报的首部和数据  
  43.     memset(package, 0, sizeof(package));  
  44.   
  45.     ip = (struct iphead*)package;  
  46.     icmp = (struct icmphead*)(package+sizeof(struct iphead)); //IP数据报数据字段仅仅包含一个ICMP首部  
  47.     sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //创建套接字  
  48.     if(sockfd < 0){  
  49.         printf("Create socket failed\n");  
  50.         return -1;  
  51.     }  
  52.     conn.sin_family = AF_INET;  
  53.     conn.sin_addr.s_addr = inet_addr("192.168.230.135");  
  54.     int one = 1;  
  55.     if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0){  //设置套接字行为,此处设置套接字不添加IP首部  
  56.         printf("setsockopt failed!\n");  
  57.         return -1;  
  58.     }  
  59.     /*设置IP首部各个字段的值*/    
  60.     ip->ip_version = 4;   
  61.     ip->ip_hl = 5;  
  62.     ip->ip_tos = 0;  
  63.     ip->ip_len = htons(sizeof(struct iphead) + sizeof(struct icmphead)); //关于htons()、htonl()的作用,可自行百度      
  64.     ip->ip_id = htons(1);  
  65.     ip->ip_off = htons(0x4000);  
  66.     ip->ip_ttl = 10;  
  67.     ip->ip_pro = IPPROTO_ICMP;  
  68.     ip->ip_src = htonl(inet_addr("192.168.230.135"));  
  69.     ip->ip_dst = htonl(inet_addr("192.168.230.135"));  
  70.     printf("ipcksum : %d\n", cksum(package, 20));   
  71.     ip->ip_sum = cksum(package, 20);  // 计算校验和,应当在其他字段之后设置(实验中发现检验和会被自动添加上)  
  72.       
  73.     /*设置ICMP首部各字段值*/  
  74.     icmp->icmp_type = 8;  
  75.     icmp->icmp_code = 0;  
  76.     icmp->icmp_id = 1;  
  77.     icmp->icmp_seq = 0;  
  78.     icmp->icmp_sum = (cksum(package+20, 8));  
  79.     /*接下来发送IP数据报即可*/  
  80.     if(sendto(sockfd, package, htons(ip->ip_len), 0,(struct sockaddr *)&conn, sizeof(struct sockaddr)) < 0){  
  81.     printf("send failed\n");   
  82.     return -1;  
  83.     }  
  84.     printf("send successful\n");      
  85.     return 0;  
  86. }</span>  



[plain] view plain copy
  1. <span style="font-size:18px;">#include<stdio.h>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #include<sys/socket.h>  
  5. #include<sys/types.h>  
  6. #include<netinet/in.h>  
  7. #include<unistd.h>  
  8. #include<linux/if_ether.h>  
  9.   
  10. unsigned short int cksum(char buffer[], int size){  //校验函数  
  11.     unsigned long sum = 0;  
  12.     unsigned short int answer;  
  13.     unsigned short int *temp;  
  14.     temp = (short int *)buffer;  
  15.     for( ; temp<buffer+size; temp+=1)  
  16.         sum += *temp;  
  17.     sum = (sum >> 16) + (sum & 0xffff);  
  18.     sum += (sum >> 16);  
  19.     answer = ~sum;  
  20.     return answer;  
  21. }  
  22.   
  23. int main(){  
  24.     unsigned char buffer[1024];  
  25.       
  26.   //  int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//不知为啥,无法设置原始套接字在网络层抓IP数据报  
  27.     int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); //此处,利用原始套接字在数据链路层抓取MAC帧,去掉  
  28.     if(sockfd < 0){                                            //14个字节的MAC帧首部即可  
  29.         printf("create sock failed\n");  
  30.     return -1;  
  31.     }      
  32.     int n = recvfrom(sockfd, buffer, 1024, 0, NULL, NULL); //接收MAC帧  
  33.   
  34.     printf("receive %d bytes\n", n);  
  35.     for(int i=14; i<n; i++){      //去掉MAC帧首部,直接输出IP数据报每个字节的数据  
  36.     if((i-14) % 16 == 0)  
  37.         printf("\n");  
  38.     printf("%d ",buffer[i]);  
  39.     }  
  40.     printf("\n");  
  41.     printf("ipcksum: %d\n", cksum(buffer+14, 20)); //此处再次校验时,应当输出0  
  42.     return 0;  
  43. }</span>  

这是之前参考过的一篇文章,写的还可以:http://www.it165.net/pro/html/201208/3450.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值