Linux ping c实现

news2024/11/16 11:44:01

        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 printf

typedef 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]);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2163088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务设计原则介绍

在Java或任何软件开发中&#xff0c;设计服务时遵循一些核心原则是非常重要的&#xff0c;这些原则不仅有助于构建高质量、可维护的软件系统&#xff0c;还能提高系统的可扩展性和可重用性。以下是一些关键的服务设计原则&#xff1a; 单一职责原则&#xff08;SingleResponsib…

将python代码文件转成Cython 编译问题集

准备setup.py from distutils.core import setup from Cython.Build import cythonize import glob# 指定目标目录 python setup.py build -c mingw32 target_dir "src"# 使用glob模块匹配目录中的所有.pyx文件 pyx_files glob.glob(target_dir "/**/*.py&q…

路政通 | OPENAIGC开发者大赛高校组AI创新之星奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

Vue+Tui-image-editor实现图片编辑(涂鸦,裁剪,标注,旋转,滤镜)

目录 前言 效果展示 涂鸦 裁剪 标注 旋转 滤镜 安装 使用 中文化自定义样式按钮优化 参考链接 前言 需求&#xff1a;对图片进行旋转、缩放、裁剪、涂鸦、标注、添加文本等。 效果展示 涂鸦 裁剪 标注 旋转 滤镜 安装 npm i tui-image-editor // or yarn add tui-image…

【hot100-java】【环形链表 II】

印象题 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode detectCycle(ListNode head) {ListNode fasthea…

①无需编程 独立通道 Modbus主站EtherNet/IP转ModbusRTU/ASCII工业EIP网关串口服务器

Modbus主站EtherNet/IP转ModbusRTU/ASCII工业EIP网关串口服务器https://item.taobao.com/item.htm?ftt&id743840591638 EtherNet/IP 串口网关 EtherNet/IP 转 RS485 型号 2路总线EIP网关 MS-A1-2021 4路总线EIP网关 MS-A1-2041 4路总线EIP网关&#xff08;双网口&am…

NASA数据集:ATLAS/ICESat-2 L3 A海冰干岸,版本6

目录 ATLAS/ICESat-2 L3 A海冰干岸&#xff0c;版本6 简介 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ATLAS/ICESat-2 L3 A海冰干岸&#xff0c;版本6 简介 ICESat-2天文台利用光计数激光雷达&#xff08;ATLAS仪器&#xff09;和辅助系统&#xff08;GPS、…

速通LLaMA3:《The Llama 3 Herd of Models》全文解读

文章目录 概览论文开篇IntroductionGeneral OverviewPre-TrainingPre-Training DataModel ArchitectureInfrastructure, Scaling, and EfficiencyTraining Recipe Post-TrainingResultsVision ExperimentsSpeech Experiments⭐Related WorkConclusionLlama 3 模型中的数学原理1…

mybatisplus介绍以及使用(下)

目录 一、mybatisplus扩展功能 1、代码生成 1.1 安装插件 1.2 使用 2、逻辑删除 二、插件功能 1、分页插件 2、示例 写在前面&#xff1a; 在上篇的mybatisplus中介绍到了其概念&#xff0c;其中包括了什么是mybatisplus以及已经有了mybatis但是我们为什么使用它&#x…

【MySQL内置数据库】information_schema

MySQL8.0.37 统计 1 ADMINISTRABLE_ROLE_AUTHORIZATIONS 2 APPLICABLE_ROLES 3 CHARACTER_SETS 提供了关于可用字符集的信息 4 CHECK_CONSTRAINTS 5 COLLATIONS 提供了关于字符集的排序规则的信息 6 COLLATION_CHARACTER_SET_APPLICABILITY 7 COLUMNS …

基于JAVA+SpringBoot+Vue的医院后台管理系统

基于JAVASpringBootVue的医院后台管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈…

Redis 消息队列

认识消息队列 消息队列&#xff08;Message Queue&#xff09;字面意思就是存放消息的队列&#xff0c;最简单的消息队列模型包括 3 个角色 消息队列&#xff1a;存储和管理消息&#xff0c;也被称为消息代理&#xff08;Message Broker&#xff09; 生产者&#xff1a;发送消…

游戏开发2025年最新版——八股文面试题(unity,虚幻,cocos都适用)

1.静态合批与动态合批的原理是什么&#xff1f;有什么限制条件&#xff1f;为什么&#xff1f;对CPU和GPU产生的影响分别是什么&#xff1f; 原理&#xff1a;Unity运行时可以将一些物体进行合并&#xff0c;从而用一个描绘调用来渲染他们&#xff0c;就是一个drawcall批次。 限…

【day20240925】常见数据集科普

文章目录 常见数据集Fashion-MNISTCIFAR-10CIFAR-100IMDbTiny Imagenet 常见数据集 Fashion-MNIST CIFAR-10 CIFAR-100 IMDb Tiny-ImageNet Fashion-MNIST Fashion-MNIST数据集涵盖了来自 10 种类别的共 7 万个不同商品的正面图片。它的大小、格式和训练集 / 测试集划分与原…

pycharm 使用 translation 插件通过openai进行翻译

pycharm 使用 translation 插件通过openai进行翻译 1. 安装插件2. 配置插件3. 翻译 1. 安装插件 2. 配置插件 3. 翻译 调用 openai 时使用的提示词如下&#xff1a; <|im_start|>system\nYou are a translation engine that can only translate text and cannot interpr…

WebSocket实现在线聊天室

项目实现源码&#xff1a; 前端源码 后端源码 1.常见的消息推送方式 1.1 轮询 1.1.1 轮询的概念 客户端以固定的事件间隔&#xff08;例如每秒或几分钟&#xff09;向服务器发送HTTP请求&#xff0c;服务器收到请求后&#xff0c;处理请求并返回数据给客户端 轮询具体实现htt…

Redis的一些数据类型(一)

&#xff08;一&#xff09;数据类型 我们说redis是key value键值对的方式存储数据&#xff0c;key是字符串&#xff0c;而value是一些数据结构,那今天就来说一下value存储的数据。 我们数据结构包含&#xff0c;String&#xff0c;hash&#xff0c;list&#xff0c;set和zest但…

SegFormer网络结构的学习和重构

因为太多的博客并没有深入理解,本文是自己学习后加入自己深入理解的总结记录&#xff0c;方便自己以后查看。 segformer中encoder、decoder的详解。 学习前言 一起来学习Segformer的原理,如果有用的话&#xff0c;请记得点赞关注哦。 一、Segformer的网络结构图 网络结构&…

反转字符串 II--力扣541

反转字符串 II 题目思路代码 题目 思路 本题的关键在于理解每隔 2k 个字符的前 k 个字符进行反转&#xff0c;剩余字符小于 2k 但大于或等于 k 个&#xff0c;则反转前 k 个字符。并且剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。 让i每次跳2k&#xff0c;成为每一次…

Xshell 连接 VMware虚拟机操作 截图和使用

Xshell 连接 VMware虚拟机操作 文章目录 Xshell 连接 VMware虚拟机操作一、本机环境截图1.1配置 Xshell环境截图VWware 配置环境截图最后下载地址 一、本机环境截图 1.1配置 Xshell环境截图 VWware 配置环境截图 最后 下载地址 vmware https://www.vmware.com/ VMware总部位于…