当前位置: 首页 > news >正文

Linux ping c实现

        linux下ping程序的c实现

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdint.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>#define DATA_SIZE 32#define pri_debug printf
#define pri_error printftypedef struct tag_icmp_header
{u_int8_t  type;u_int8_t  code;u_int16_t check_sum;u_int16_t id;u_int16_t seq;
} icmp_header;typedef struct tag_iphdr
{u_int8_t        ip_head_verlen;u_int8_t        ip_tos;unsigned short  ip_length;unsigned short  ip_id;unsigned short  ip_flags;u_int8_t        ip_ttl;u_int8_t        ip_protacol;unsigned short  ip_checksum;int             ip_source;int             ip_destination;
} ip_header;unsigned short generation_checksum(unsigned short * buf, int size)
{unsigned long cksum = 0;while(size > 1){cksum += *buf++;size -= sizeof(unsigned short);}if(size){cksum += *buf++;}cksum =  (cksum>>16) + (cksum & 0xffff);cksum += (cksum>>16);return (unsigned short)(~cksum);
}double get_time_interval(struct timeval * start, struct timeval * end)
{double interval;struct timeval tp;tp.tv_sec = end->tv_sec - start->tv_sec;tp.tv_usec = end->tv_usec - start->tv_usec;if(tp.tv_usec < 0){tp.tv_sec -= 1;tp.tv_usec += 1000000;}interval = tp.tv_sec * 1000 + tp.tv_usec * 0.001;return interval;
}int ping_host_ip(const char * domain)
{int i;int ret = -1;int client_fd;int size = 50 * 1024;struct timeval timeout;char * icmp;in_addr_t dest_ip;icmp_header * icmp_head;struct sockaddr_in dest_socket_addr;if(domain == NULL){pri_debug("ping_host_ip domain is NULL!\n");return ret;}dest_ip = inet_addr(domain);if(dest_ip == INADDR_NONE){struct hostent* p_hostent = gethostbyname(domain);if(p_hostent){dest_ip = (*(in_addr_t*)p_hostent->h_addr);}}client_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);if (client_fd == -1){pri_error("socket error: %s!\n", strerror(errno));return ret;}timeout.tv_sec = 1;timeout.tv_usec = 0;setsockopt(client_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));if(setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval))){pri_error("setsocketopt SO_RCVTIMEO error!\n");return ret;}if(setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval))){pri_error("setsockopt SO_SNDTIMEO error!\n");return ret;}dest_socket_addr.sin_family = AF_INET;dest_socket_addr.sin_addr.s_addr = dest_ip;dest_socket_addr.sin_port = htons(0);memset(dest_socket_addr.sin_zero, 0, sizeof(dest_socket_addr.sin_zero));icmp = (char *)malloc(sizeof(icmp_header) + DATA_SIZE);memset(icmp, 0, sizeof(icmp_header) + DATA_SIZE);icmp_head = (icmp_header *)icmp;icmp_head->type = 8;icmp_head->code = 0;icmp_head->id = 1;pri_debug("PING %s (%s).\n", domain, inet_ntoa(*((struct in_addr*)&dest_ip)));for(i = 0; i < 3; i++){struct timeval start;struct timeval end;long result;struct sockaddr_in from;socklen_t from_packet_len;long read_length;char recv_buf[1024];icmp_head->seq = htons(i);icmp_head->check_sum = 0;icmp_head->check_sum = generation_checksum((unsigned short*)icmp,sizeof(icmp_header) + DATA_SIZE);gettimeofday(&start, NULL);result = sendto(client_fd, icmp, sizeof(icmp_header) +DATA_SIZE, 0, (struct sockaddr *)&dest_socket_addr,sizeof(dest_socket_addr));if(result == -1){pri_debug("PING: sendto: Network is unreachable\n");continue;}from_packet_len = sizeof(from);memset(recv_buf, 0, sizeof(recv_buf));while(1){read_length = recvfrom(client_fd, recv_buf, 1024, 0,(struct sockaddr*)&from, &from_packet_len);gettimeofday( &end, NULL );if(read_length != -1){ip_header * recv_ip_header = (ip_header*)recv_buf;int ip_ttl = (int)recv_ip_header->ip_ttl;icmp_header * recv_icmp_header = (icmp_header *)(recv_buf +(recv_ip_header->ip_head_verlen & 0x0F) * 4);if(recv_icmp_header->type != 0){pri_error("error type %d received, error code %d \n", recv_icmp_header->type, recv_icmp_header->code);break;}if(recv_icmp_header->id != icmp_head->id){pri_error("some else's packet\n");break;}if(read_length >= (long)(sizeof(ip_header) +sizeof(icmp_header) + DATA_SIZE)){pri_debug("%ld bytes from %s (%s): icmp_seq=%d ttl=%d time=%.2f ms\n",read_length, domain, inet_ntoa(from.sin_addr), recv_icmp_header->seq / 256,ip_ttl, get_time_interval(&start, &end));ret = 0;// 证明网络通畅,后续的包已经不许再需要验证goto PING_EXIT;}break;}else{pri_error("receive data error!\n");break;}}}PING_EXIT:if(NULL != icmp){free(icmp);icmp = NULL;}if(client_fd != -1){close(client_fd);}return ret;
}int main(int argc, char **argv)
{ping_host_ip(argv[1]);
}

相关文章:

  • 【AI创作组】MATLAB基础语法总结
  • 物理学基础精解【24】
  • 前端全屏模式切换
  • 《 Spring Boot实战:优雅构建责任链模式投诉处理业务》
  • unreal engine5制作动作类游戏时,我们使用刀剑等武器攻击怪物或敌方单位时,发现攻击特效、伤害等没有触发
  • 阿里云部署1Panel(失败版)
  • STM32单片机编程调试常见问题(一) HardFault_Handler故障分析与解决
  • c语言200例 64
  • 深入解析:Kubernetes 如何使用 etcd 作为配置中心和注册中心
  • MacOS Sequoia安装geant4.10.07
  • 赵长鹏今日获释,下一步会做什么?币安透露2024年加密货币牛市的投资策略!
  • 教师工作量|基于springBoot的教师工作量管理系统设计与实现(附项目源码+论文+数据库)
  • 【漏洞复现】数字通云平台智慧政务 login 存在登录绕过漏洞
  • C++ 标准模板库(STL)之集合(set)
  • GO Fsnotify学习与使用
  • 【mysql】环境安装、服务启动、密码设置
  • Akka系列(七):Actor持久化之Akka persistence
  • docker-consul
  • JavaScript函数式编程(一)
  • js数组之filter
  • Linux中的硬链接与软链接
  • maya建模与骨骼动画快速实现人工鱼
  • Meteor的表单提交:Form
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Sublime text 3 3103 注册码
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 观察者模式实现非直接耦合
  • 面试总结JavaScript篇
  • 爬虫模拟登陆 SegmentFault
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 深度学习入门:10门免费线上课程推荐
  • 微信小程序开发问题汇总
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • Linux权限管理(week1_day5)--技术流ken
  • 带你开发类似Pokemon Go的AR游戏
  • 移动端高清、多屏适配方案
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​linux启动进程的方式
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​VRRP 虚拟路由冗余协议(华为)
  • #{}和${}的区别是什么 -- java面试
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (第三期)书生大模型实战营——InternVL(冷笑话大师)部署微调实践
  • (二)Linux——Linux常用指令
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (十七)Flink 容错机制
  • (数据大屏)(Hadoop)基于SSM框架的学院校友管理系统的设计与实现+文档
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (万字长文)Spring的核心知识尽揽其中
  • (一)Dubbo快速入门、介绍、使用