dfdfssg 2023-11-27 11:10 采纳率: 0%
浏览 12
已结题

有接网络协议编程代做吗,又长

使用c语言基于Socket使用ICMP协议发现网络中的活动主机。本学期客舍,具体内容可饲料

  • 写回答

16条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2023-11-27 11:11
    关注
    获得0.60元问题酬金

    引自强大而免费的微信小程序:皆我百晓生

    1. 了解ICMP协议

    ICMP(Internet Control Message Protocol)是网络层的一个协议,用于在IP网络中传递控制消息。它主要用于检测网络的连接状况和故障诊断。

    2. 创建Socket

    首先,我们需要创建一个Socket来进行网络通信。Socket是网络编程中用于实现网络连接的一种机制。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/ip_icmp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    
    int create_socket()
    {
        int sockfd;
        sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if (sockfd < 0) {
            perror("Could not create socket");
            exit(EXIT_FAILURE);
        }
        return sockfd;
    }
    

    在上面的代码中,我们使用socket函数创建了一个原始套接字,使用SOCK_RAW参数表示它是一个原始套接字,可以直接发送和接收IP包的数据。

    3. 构建ICMP请求报文

    将IP地址封装到IP头部,将ICMP请求报文封装到IP数据部分。

    typedef struct {
        struct icmphdr icmp_header;
        char data[64];
    } icmp_packet_t;
    
    icmp_packet_t create_icmp_packet()
    {
        icmp_packet_t packet;
        memset(&packet, 0, sizeof(packet));
    
        packet.icmp_header.type = ICMP_ECHO;
        packet.icmp_header.un.echo.id = getpid();
    
        strcpy(packet.data, "This is the payload of the ICMP packet.");
    
        packet.icmp_header.checksum = 0;
        packet.icmp_header.checksum = checksum((unsigned short*)&packet, sizeof(packet));
    
        return packet;
    }
    

    在上述代码中,我们定义了一个icmp_packet_t结构体用于存储ICMP请求报文,其中icmp_header字段是ICMP报文头部,data字段是ICMP报文的数据部分。我们设置了ICMP报文的类型为ICMP_ECHO,即回显请求报文,并给ICMP报文创建一个唯一的ID,以便在收到回复报文时进行匹配。最后,我们计算了ICMP报文的校验和,并将其赋值到checksum字段中。

    4. 发送ICMP报文

    void send_icmp_packet(int sockfd, const struct sockaddr_in *dest_addr, const icmp_packet_t *packet)
    {
        ssize_t bytes_sent;
        bytes_sent = sendto(sockfd, packet, sizeof(*packet), 0,
                            (struct sockaddr*)dest_addr, sizeof(*dest_addr));
        if (bytes_sent < 0) {
            perror("Failed to send ICMP packet");
            exit(EXIT_FAILURE);
        }
    }
    

    上述代码中,我们使用sendto函数将构建好的ICMP报文发送到目标主机。其中,sockfd参数是Socket的文件描述符,packet参数是要发送的ICMP报文。

    5. 接收ICMP响应报文

    icmp_packet_t receive_icmp_packet(int sockfd, const struct sockaddr_in *src_addr)
    {
        icmp_packet_t packet;
        socklen_t addrlen = sizeof(struct sockaddr_in);
    
        ssize_t bytes_received;
        bytes_received = recvfrom(sockfd, &packet, sizeof(packet), 0,
                                    (struct sockaddr*)src_addr, &addrlen);
        if (bytes_received < 0) {
            perror("Failed to receive ICMP packet");
            exit(EXIT_FAILURE);
        }
    
        return packet;
    }
    

    在上面的代码中,我们使用recvfrom函数从目标主机接收ICMP响应报文。其中,sockfd参数是Socket的文件描述符,src_addr参数是保存发送ICMP报文的源主机的地址的结构体指针。

    6. 解析ICMP响应报文

    void parse_icmp_packet(const icmp_packet_t *packet, const struct sockaddr_in *src_addr)
    {
        printf("Received ICMP packet from %s\n", inet_ntoa(src_addr->sin_addr));
    
        if (packet->icmp_header.type == ICMP_ECHOREPLY) {
            printf("ICMP echo reply received\n");
            printf("Payload: %s\n", packet->data);
        }
    }
    

    在上面的代码中,我们首先打印出发送ICMP报文的源主机的IP地址。然后,判断接收到的ICMP报文的类型是否为回显应答(ICMP_ECHOREPLY),如果是则打印出ICMP报文的数据部分。

    7. 主函数

    最后,我们将上述函数组合在一起,实现发现网络中的活动主机。

    int main()
    {
        int sockfd;
        struct sockaddr_in dest_addr, src_addr;
        icmp_packet_t packet, received_packet;
    
        // 创建原始套接字
        sockfd = create_socket();
    
        // 设置目标主机地址
        memset(&dest_addr, 0, sizeof(dest_addr));
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = 0;
        inet_pton(AF_INET, "目标主机IP地址", &(dest_addr.sin_addr));
    
        // 构建ICMP请求报文
        packet = create_icmp_packet();
    
        // 发送ICMP请求报文
        send_icmp_packet(sockfd, &dest_addr, &packet);
    
        // 接收ICMP响应报文
        received_packet = receive_icmp_packet(sockfd, &src_addr);
    
        // 解析ICMP响应报文
        parse_icmp_packet(&received_packet, &src_addr);
    
        // 关闭套接字
        close(sockfd);
    
        return 0;
    }
    

    在上述代码中,我们首先创建了一个原始套接字,然后设置了目标主机的地址。接着,我们构建了一个ICMP请求报文,并发送给目标主机。然后,我们接收目标主机的ICMP响应报文,并解析报文内容。最后,我们关闭套接字。

    这样,我们就实现了使用C语言基于Socket使用ICMP协议发现网络中的活动主机。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 12月5日
  • 修改了问题 11月27日
  • 创建了问题 11月27日