我正在尝试用C创建一个ICMP ping测试程序,但是在成功发送数据包时遇到了困难. sendto函数返回字节数和所有内容但实际上没有发送数据包.我已经在目标计算机上使用WireShark验证了这一点.主机上的常规ping工作正常,但在WireShark中显示.

这是我的代码:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

unsigned short cksum(unsigned short *addr, int len);

int main(int argc, char *argv[])

{

int sock;

char send_buf[400], recv_buf[400], src_name[256], src_ip[15], dst_ip[15];

struct ip *ip = (struct ip *)send_buf;

struct icmp *icmp = (struct icmp *)(ip + 1);

struct hostent *src_hp, *dst_hp;

struct sockaddr_in src, dst;

struct timeval t;

int on;

int num = 10;

int failed_count = 0;

int bytes_sent, bytes_recv;

int dst_addr_len;

int result;

fd_set socks;

/* Initialize variables */

on = 1;

memset(send_buf, 0, sizeof(send_buf));

/* Check for valid args */

if(argc < 2)

{

printf("\nUsage: %s \n", argv[0]);

printf("- dst_server is the target\n");

exit(EXIT_FAILURE);

}

/* Check for root access */

if (getuid() != 0)

{

fprintf(stderr, "%s: This program requires root privileges!\n", argv[0]);

exit(EXIT_FAILURE);

}

/* Get source IP address */

if(gethostname(src_name, sizeof(src_name)) < 0)

{

perror("gethostname() error");

exit(EXIT_FAILURE);

}

else

{

if((src_hp = gethostbyname(src_name)) == NULL)

{

fprintf(stderr, "%s: Can't resolve, unknown source.\n", src_name);

exit(EXIT_FAILURE);

}

else

ip->ip_src = (*(struct in_addr *)src_hp->h_addr);

}

/* Get destination IP address */

if((dst_hp = gethostbyname(argv[1])) == NULL)

{

if((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1)

{

fprintf(stderr, "%s: Can't resolve, unknown destination.\n", argv[1]);

exit(EXIT_FAILURE);

}

}

else

{

ip->ip_dst = (*(struct in_addr *)dst_hp->h_addr);

dst.sin_addr = (*(struct in_addr *)dst_hp->h_addr);

}

sprintf(src_ip, "%s", inet_ntoa(ip->ip_src));

sprintf(dst_ip, "%s", inet_ntoa(ip->ip_dst));

printf("Source IP: '%s' -- Destination IP: '%s'\n", src_ip, dst_ip);

/* Create RAW socket */

if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)

{

perror("socket() error");

/* If something wrong, just exit */

exit(EXIT_FAILURE);

}

/* Socket options, tell the kernel we provide the IP structure */

if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)

{

perror("setsockopt() for IP_HDRINCL error");

exit(EXIT_FAILURE);

}

/* IP structure, check the ip.h */

ip->ip_v = 4;

ip->ip_hl = 5;

ip->ip_tos = 0;

ip->ip_len = htons(sizeof(send_buf));

ip->ip_id = htons(321);

ip->ip_off = htons(0);

ip->ip_ttl = 255;

ip->ip_p = IPPROTO_ICMP;

ip->ip_sum = 0;

/* ICMP structure, check ip_icmp.h */

icmp->icmp_type = ICMP_ECHO;

icmp->icmp_code = 0;

icmp->icmp_id = 123;

icmp->icmp_seq = 0;

/* Set up destination address family */

dst.sin_family = AF_INET;

/* Loop based on the packet number */

for(int i = 1; i <= num; i++)

{

/* Header checksums */

icmp->icmp_cksum = 0;

ip->ip_sum = cksum((unsigned short *)send_buf, ip->ip_hl);

icmp->icmp_cksum = cksum((unsigned short *)icmp, sizeof(send_buf) - sizeof(struct icmp));

/* Get destination address length */

dst_addr_len = sizeof(dst);

/* Set listening timeout */

t.tv_sec = 5;

t.tv_usec = 0;

/* Set socket listening descriptors */

FD_ZERO(&socks);

FD_SET(sock, &socks);

/* Send packet */

if((bytes_sent = sendto(sock, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&dst, dst_addr_len)) < 0)

{

perror("sendto() error");

failed_count++;

printf("Failed to send packet.\n");

fflush(stdout);

}

else

{

printf("Sent %d byte packet... ", bytes_sent);

fflush(stdout);

/* Listen for the response or timeout */

if((result = select(sock + 1, &socks, NULL, NULL, &t)) < 0)

{

perror("select() error");

failed_count++;

printf("Error receiving packet!\n");

}

else if (result > 0)

{

printf("Waiting for packet... ");

fflush(stdout);

if((bytes_recv = recvfrom(sock, recv_buf, sizeof(ip) + sizeof(icmp) + sizeof(recv_buf), 0, (struct sockaddr *)&dst, (socklen_t *)&dst_addr_len)) < 0)

{

perror("recvfrom() error");

failed_count++;

fflush(stdout);

}

else

printf("Received %d byte packet!\n", bytes_recv);

}

else

{

printf("Failed to receive packet!\n");

failed_count++;

}

fflush(stdout);

icmp->icmp_seq++;

}

}

/* Display success rate */

printf("Ping test completed with %d%% success rate.\n", (((num - failed_count) / num) * 100));

/* close socket */

close(sock);

return 0;

}

/* One's Complement checksum algorithm */

unsigned short cksum(unsigned short *addr, int len)

{

int nleft = len;

int sum = 0;

unsigned short *w = addr;

unsigned short answer = 0;

while (nleft > 1)

{

sum += *w++;

nleft -= 2;

}

if (nleft == 1)

{

*(unsigned char *)(&answer) = *(unsigned char *)w;

sum += answer;

}

sum = (sum >> 16) + (sum & 0xffff);

sum += (sum >> 16);

answer = ~sum;

return (answer);

}

对我做错了什么的想法?校验和还好吗?两者都使用0可以吗?

编辑:好的,所以我设法得到正确发送的数据包,感谢下面的人!目标计算机将发回回信回复.但是,现在,我的程序没有收到答复. select()函数总是超时.我已经更新了上面的代码.

编辑2:好吧,我已经开始工作了!我需要将套接字协议设置为IPPROTO_ICMP而不是IPPROTO_RAW,它工作得很好!再次感谢你们的评论!真有帮助!看起来我只能将一个答案标记为正确,但你们都帮助解决这个问题.

数据包收发c语言程序,在C程序中发送ICMP数据包相关推荐

  1. C语言程序周期接收虚拟串口发送的数据

    背景 我之前的一篇博客讲解了怎么使用虚拟串口和串口调试助手:虚拟串口模拟器和串口调试助手使用教程,这次我们在此基础上继续来使用虚拟串口周期发送和接收功能. 我们知道,在Windows的操作系统上,将串 ...

  2. 《数据科学:R语言实现》——3.12 估计缺失数据

    本节书摘来自华章出版社<数据科学:R语言实现>一 书中的第3章,第3.12节,作者:R for Data Science Cookbook 丘祐玮(David Chiu),更多章节内容可以 ...

  3. php7 mysql json 小程序_微信小程序php传递post请求发送json数据以获取小程序码

    困扰了两天的问题终于解决了! 用php传递post请求,发送json数据到微信小程序提供的接口,以此获得微信小程序码,下面是代码展示:<?php //需要传递的json数据 //能传递的参数,详 ...

  4. 【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  5. 数据包收发c语言程序,使用C在套接字编程中创建数据包以及发送和接收数据包的正确方法...

    指针pkt未在您的应用程序中定义.您有两种选择: 1)将pkt声明为正常变量 struct packet pkt; pkt.srcID = 01; .... send(sockfd, &pkt ...

  6. python构造icmp数据包_如何在python中构造ICMP数据包

    为了学习,我目前正在尝试创建一个简单的python porgram来向某个设备发送ICMP ping数据包.为了开始,我查看了python模块Pyping:https://github.com/Akh ...

  7. 数据丢包怎么修复_一种网络传输中实时音频数据丢包恢复的方法与流程

    本发明涉及通信技术领域,具体涉及一种网络传输中实时音频数据丢包恢复的方法. 背景技术: 随着通信技术的发展,音频传输系统对实时性和准确性的要求越来越高.在网络的音频传输过程中,影响音频音质的主要因素是 ...

  8. python如何收集数据的方法有哪些_class类在python中获取金融数据的实例方法

    我们搜集金融数据,通常想要的是利用爬虫的方法.其实我们最近所学的class不仅可以进行类调用,在获取数据方面同样是可行的,很多小伙伴都比较关注理财方面的情况,对金融数据的需要也是比较多的.下面就cla ...

  9. 在XML中发送二进制数据

    作者: BUILDER.COM XML通常被认为是用文本来描述数据的一种方法.例如,元素给出了文本名,元素的内容通常是基于文本的.但是有时候你需要输入数据而不是文本到你的XML文档.让我们来考虑你可能 ...

最新文章

  1. 单片机ch2o程序_基于单片机的室内甲醛浓度检测系统
  2. Salesforce宣布5.82亿美元收购文件编辑公司Quip
  3. Markdown简明使用
  4. iptables说明(转)
  5. opera官方教程 预订二
  6. CenterPoint的环境配置error大全【已全部解决】
  7. VMware12虚拟机怎么下载安装?保姆级安装教程,让你一分钟学会
  8. 《工程学导论》读书笔记-2
  9. EXCEL电子档色环电阻计算器
  10. 自组织神经网络:自组织特征映射SOM网络
  11. APP开通支付宝支付 转账功能
  12. android 屏幕分辨率获取,Android获取屏幕分辨率的三种方法
  13. MySQL - 全局锁、表级锁、行级锁、元数据锁、自增锁、意向锁、共享锁、独占锁、记录锁、间隙锁、临键锁、死锁
  14. 2021-03-27 深度信念网络(DBN)学习笔记
  15. 【物联网中间件平台-02】YFIOs技术白皮书(V1.1)
  16. 恶意代码机理与防护笔记
  17. 夜晚拍照出现耀斑的原因
  18. 华罗庚统筹法与计算机专业,华罗庚的《统筹方法》
  19. 什么是CRM?2023年15家全球顶级CRM系统推荐
  20. 深度学习——NiN网络模型(笔记)

热门文章

  1. 模拟银行账户转账系统(简单模拟)
  2. Linux驱动学习笔记 -- 驱动总线实验
  3. ROS小车打造(七)--YOLO运行ROS例子--TX2安装darknet_ros
  4. 小兔鲜案例注册,登录,索引的实现效果
  5. 项目实战--响应式导航[1]
  6. Winform初学 ---01设计一个简易的浏览器
  7. 指针数组,数组指针与二维数组剖析
  8. 数据挖掘:概念与技术
  9. php接收图片微信小程序,微信小程序如何获取相册照片
  10. 【第十一届“泰迪杯”数据挖掘挑战赛】泰迪杯c题爬虫采集数据(源码+数据)