Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 套接字关闭(sd)呼叫(发送arp请求后)被卡住(挂起)_C_Linux_Network Programming - Fatal编程技术网

C 套接字关闭(sd)呼叫(发送arp请求后)被卡住(挂起)

C 套接字关闭(sd)呼叫(发送arp请求后)被卡住(挂起),c,linux,network-programming,C,Linux,Network Programming,发送arp请求后,下面的create_和

发送arp请求后,下面的
create_和
函数有时会挂起在
close(sd)
调用中。这是因为创建了带有
htons(ETH\u P\u ALL)
的套接字吗?我认为发送免费的ARP请求应该是
htons(ETH\u P\u ARP)

如果我们将套接字协议类型改为
ETH_p_ARP
而不是
ETH_p_ALL
,会有任何副作用吗

create_and_send_arp(string port, IpAddress& addr)
{
    const char *interface;
    int frame_length, sd, bytes;
    arp_hdr arphdr;
    UINT32 address = addr.addr.ipv4.s_addr;

    uint8_t src_ip[4], src_mac[6], dst_mac[6], ether_frame[IP_MAXPACKET];
    struct sockaddr_ll device;
    struct ifreq ifr;


    // Interface to send packet through.
    interface = port.c_str();
    memcpy (src_ip, &address, 4 * sizeof (uint8_t));

     // Submit request for a socket descriptor to look up interface.
    if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
      perror ("socket() failed to get socket descriptor for using ioctl()");
      return;
    }

    // Use ioctl() to look up interface name and get its MAC address.
    memset (&ifr, 0, sizeof (ifr));
    snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
    if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
      perror ("ioctl() failed to get source MAC address");
      close (sd);
      return;
    }

    close (sd);

    // Copy source MAC address.
    memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));

    // Find interface index from interface name and store index in
    // struct sockaddr_ll device, which will be used as an argument of sendto().
    if ((device.sll_ifindex = if_nametoindex (interface)) == 0) {
      perror ("if_nametoindex() failed to obtain interface index");
      return;
    }

    // Set destination MAC address: broadcast address
    memset (dst_mac, 0xff, 6 * sizeof (uint8_t));

    memcpy (&arphdr.sender_ip, src_ip, 4 * sizeof (uint8_t));
    memcpy (&arphdr.target_ip, src_ip, 4 * sizeof (uint8_t));

    // Fill out sockaddr_ll.
    device.sll_family = AF_PACKET;
    memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t));
    device.sll_halen = htons (6);

    // ARP header

    // Hardware type (16 bits): 1 for ethernet
    arphdr.htype = htons (1);

    // Protocol type (16 bits): 2048 for IP
    arphdr.ptype = htons (ETH_P_IP);

    // Hardware address length (8 bits): 6 bytes for MAC address
    arphdr.hlen = 6;

    // Protocol address length (8 bits): 4 bytes for IPv4 address
    arphdr.plen = 4;

    // OpCode: 1 for ARP request
    arphdr.opcode = htons (ARPOP_REQUEST);

    // Sender hardware address (48 bits): MAC address
    memcpy (&arphdr.sender_mac, src_mac, 6 * sizeof (uint8_t));

    // Target hardware address (48 bits): zero
    memset (&arphdr.target_mac, 0, 6 * sizeof (uint8_t));

    // Fill out ethernet frame header.

    // Ethernet frame length = ethernet header (MAC + MAC + ethernet type) + ethernet data (ARP header)
    frame_length = 6 + 6 + 2 + ARP_HDRLEN;

    // Destination and Source MAC addresses
    memcpy (ether_frame, dst_mac, 6 * sizeof (uint8_t));
    memcpy (ether_frame + 6, src_mac, 6 * sizeof (uint8_t));

    // Next is ethernet type code (ETH_P_ARP for ARP).
    ether_frame[12] = ETH_P_ARP / 256;
    ether_frame[13] = ETH_P_ARP % 256;


    // ARP header
    memcpy (ether_frame + ETH_HDRLEN, &arphdr, ARP_HDRLEN * sizeof (uint8_t));

    if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ARP))) < 0) {
        perror ("socket() failed");
        return;
    }

    // Send ethernet frame to socket.
    if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) {
      perror ("sendto() failed");
      close (sd);
      return;
    }

    // Close socket descriptor.
    close (sd); // this gets stuck and hangs
    return;
    }

部分回溯表明您的程序是多线程的,而且似乎还表明您有两个线程同时运行
close()
(不一定对应于同一源代码行)。多线程为间歇性故障提供了各种机会,因此合理的诊断步骤是尝试在单线程程序中重现问题。我们正在启动一个计时器(使用libevent),在计时器到期回调函数中,我们调用此ARP请求发送方法。因此,libevent可能会在内部为每个计时器事件创建线程,并从该线程调用回调函数。最终调用create_和send_arp方法。发布的问题是关于运行时的问题。因此,请发表一篇文章,以便我们重现问题并帮助您调试。似乎OP可以在他们的程序中对htons(ETH_P_ARP)进行较小的编辑。
并在将问题发布到StackOverflow上之前对其进行测试(IMO:应该这样做)。部分回溯表明您的程序是多线程的,此外,它似乎还表明有两个线程同时运行
close()
(不一定对应于同一个源代码行)。多线程为间歇性故障提供了各种机会,因此合理的诊断步骤是尝试在单线程程序中重现问题。我们正在启动一个计时器(使用libevent),在计时器到期回调函数中,我们调用此ARP请求发送方法。因此,libevent可能会在内部为每个计时器事件创建线程,并从该线程调用回调函数。最终调用create_和send_arp方法。发布的问题是关于运行时的问题。因此,请发布一篇文章,以便我们重现问题并帮助您调试。似乎OP可以在他们的程序中对htons(ETH_P_ARP)进行轻微编辑。并在将问题发布到stackoverflow之前对其进行测试(IMO:应该这样做)
[New LWP 29815]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

#0 0x00007f33984cf750 in __close_nocancel () from /lib64/libpthread.so.0
#0 0x00007f33984cf750 in __close_nocancel () from /lib64/libpthread.so.0