概述
raw socket编程实例
2016年12月01日 00:58:28
1685人阅读
评论(0)
收藏
举报
分类:
网络编程(5)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nice_wen/article/details/53416063
由于最经做模拟TCP三次握手的实验,需要用到raw socket编程。
运行第一段代码,发送ip数据报,第二段代码接收ip数据报。需要运行第二段代码,否则将无法接收数据报。
- <span style="font-size:18px;">#include<stdio.h>
- #include<string.h>
- #include<stdlib.h>
- #include<sys/socket.h>
- #include<sys/types.h>
- #include<netinet/in.h>
- struct iphead{ //该结构体模拟IP首部(代码中,控制套接字不添加IP数据包首部,需要自己添加),</span>
- <span style="font-size:18px;"><span style="white-space:pre;"> </span>//关于各变量的含义,可对照IP数据报格式,一目了然。
- unsigned char ip_hl:4, ip_version:4; //ip_hl,ip_version各占四个bit位。
- unsigned char ip_tos;
- unsigned short int ip_len;
- unsigned short int ip_id;
- unsigned short int ip_off;
- unsigned char ip_ttl;
- unsigned char ip_pro;
- unsigned short int ip_sum;
- unsigned int ip_src;
- unsigned int ip_dst;
- };
- struct icmphead{ //</span><span style="font-size:18px;font-family:Arial, Helvetica, sans-serif;">该结构体模拟ICMP报文首部</span><span style="font-size:18px;">
- unsigned char icmp_type;
- unsigned char icmp_code;
- unsigned short int icmp_sum;
- unsigned short int icmp_id;
- unsigned short int icmp_seq;
- };
- unsigned short int cksum(char buffer[], int size){ //计算校验和,具体的算法可自行百度,或查阅资料
- unsigned long sum = 0;
- unsigned short int answer;
- unsigned short int *temp;
- temp = (short int *)buffer;
- for( ; temp<buffer+size; temp+=1){
- sum += *temp;
- }
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- answer = ~sum;
- return answer;
- }
- int main(){
- int sockfd;
- struct sockaddr_in conn;
- struct iphead *ip;
- struct icmphead *icmp;
- unsigned char package[sizeof(struct iphead) + sizeof(struct icmphead)]; //package存储IP数据报的首部和数据
- memset(package, 0, sizeof(package));
- ip = (struct iphead*)package;
- icmp = (struct icmphead*)(package+sizeof(struct iphead)); //IP数据报数据字段仅仅包含一个ICMP首部
- sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //创建套接字
- if(sockfd < 0){
- printf("Create socket failedn");
- return -1;
- }
- conn.sin_family = AF_INET;
- conn.sin_addr.s_addr = inet_addr("192.168.230.135");
- int one = 1;
- if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0){ //设置套接字行为,此处设置套接字不添加IP首部
- printf("setsockopt failed!n");
- return -1;
- }
- /*设置IP首部各个字段的值*/
- ip->ip_version = 4;
- ip->ip_hl = 5;
- ip->ip_tos = 0;
- ip->ip_len = htons(sizeof(struct iphead) + sizeof(struct icmphead)); //关于htons()、htonl()的作用,可自行百度
- ip->ip_id = htons(1);
- ip->ip_off = htons(0x4000);
- ip->ip_ttl = 10;
- ip->ip_pro = IPPROTO_ICMP;
- ip->ip_src = htonl(inet_addr("192.168.230.135"));
- ip->ip_dst = htonl(inet_addr("192.168.230.135"));
- printf("ipcksum : %dn", cksum(package, 20));
- ip->ip_sum = cksum(package, 20); // 计算校验和,应当在其他字段之后设置(实验中发现检验和会被自动添加上)
- /*设置ICMP首部各字段值*/
- icmp->icmp_type = 8;
- icmp->icmp_code = 0;
- icmp->icmp_id = 1;
- icmp->icmp_seq = 0;
- icmp->icmp_sum = (cksum(package+20, 8));
- /*接下来发送IP数据报即可*/
- if(sendto(sockfd, package, htons(ip->ip_len), 0,(struct sockaddr *)&conn, sizeof(struct sockaddr)) < 0){
- printf("send failedn");
- return -1;
- }
- printf("send successfuln");
- return 0;
- }</span>
- <span style="font-size:18px;">#include<stdio.h>
- #include<string.h>
- #include<stdlib.h>
- #include<sys/socket.h>
- #include<sys/types.h>
- #include<netinet/in.h>
- #include<unistd.h>
- #include<linux/if_ether.h>
- unsigned short int cksum(char buffer[], int size){ //校验函数
- unsigned long sum = 0;
- unsigned short int answer;
- unsigned short int *temp;
- temp = (short int *)buffer;
- for( ; temp<buffer+size; temp+=1)
- sum += *temp;
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- answer = ~sum;
- return answer;
- }
- int main(){
- unsigned char buffer[1024];
- // int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//不知为啥,无法设置原始套接字在网络层抓IP数据报
- int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); //此处,利用原始套接字在数据链路层抓取MAC帧,去掉
- if(sockfd < 0){ //14个字节的MAC帧首部即可
- printf("create sock failedn");
- return -1;
- }
- int n = recvfrom(sockfd, buffer, 1024, 0, NULL, NULL); //接收MAC帧
- printf("receive %d bytesn", n);
- for(int i=14; i<n; i++){ //去掉MAC帧首部,直接输出IP数据报每个字节的数据
- if((i-14) % 16 == 0)
- printf("n");
- printf("%d ",buffer[i]);
- }
- printf("n");
- printf("ipcksum: %dn", cksum(buffer+14, 20)); //此处再次校验时,应当输出0
- return 0;
- }</span>
这是之前参考过的一篇文章,写的还可以:http://www.it165.net/pro/html/201208/3450.html
最后
以上就是玩命网络为你收集整理的raw socket 编程实例 raw socket编程实例 的全部内容,希望文章能够帮你解决raw socket 编程实例 raw socket编程实例 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复