Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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
Linux recvfrom()不工作_Linux_Sockets - Fatal编程技术网

Linux recvfrom()不工作

Linux recvfrom()不工作,linux,sockets,Linux,Sockets,我正在尝试在linux(ubuntu)中使用原始套接字实现tracert,比如ICMP(echo)。我想我几乎实现了功能。但当我执行它时,它就不起作用了 通过测试,我发现“程序在recvfrom()停止” 我正在使用wireshark,我可以看到它正在发送和接收数据包。但是recvfrom()不起作用。它只是在等待一个包 我从wireshark上传屏幕截图 下面是我的代码 /* Copyright (C) 2011-2015 P.D. Buchan (pdbuchan@yahoo.com)

我正在尝试在linux(ubuntu)中使用原始套接字实现
tracert
,比如
ICMP
(echo)。我想我几乎实现了功能。但当我执行它时,它就不起作用了

通过测试,我发现“程序在recvfrom()停止”

我正在使用
wireshark
,我可以看到它正在发送和接收数据包。但是
recvfrom()
不起作用。它只是在等待一个包

我从
wireshark
上传屏幕截图

下面是我的代码

/*  Copyright (C) 2011-2015  P.D. Buchan (pdbuchan@yahoo.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// Send an IPv4 ICMP packet via raw socket.
// Stack fills out layer 2 (data link) information (MAC addresses) for us.
// Values set for echo request packet, includes some ICMP data.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>           // close()
#include <string.h>           // strcpy, memset(), and memcpy()

#include <netdb.h>            // struct addrinfo
#include <sys/types.h>        // needed for socket(), uint8_t, uint16_t, uint32_t
#include <sys/socket.h>       // needed for socket()
#include <netinet/in.h>       // IPPROTO_RAW, IPPROTO_IP, IPPROTO_ICMP, INET_ADDRSTRLEN
#include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
#include <netinet/ip_icmp.h>  // struct icmp, ICMP_ECHO
#include <arpa/inet.h>        // inet_pton() and inet_ntop()
#include <sys/ioctl.h>        // macro ioctl is defined
//#include <bits/ioctls.h>      // defines values for argument "request" of ioctl.
#include <net/if.h>           // struct ifreq

#include <errno.h>            // errno, perror()

// Define some constants.
#define IP4_HDRLEN 20         // IPv4 header length
#define ICMP_HDRLEN 8         // ICMP header length for echo request, excludes data

// Function prototypes
uint16_t checksum (uint16_t *, int);
char *allocate_strmem (int);
uint8_t *allocate_ustrmem (int);
int *allocate_intmem (int);

int
main (int argc, char **argv)
{
  int status, sd, *ip_flags; // status? ip_flags?
  const int on = 1; // ?
  //char *interface, *target, *src_ip, *dst_ip; // ????
  struct ip iphdr;
  struct icmp icmphdr;
  uint8_t data[1000];
  uint8_t packet[1000];
  struct addrinfo hints, *res; // hints? res?
  struct sockaddr_in *ipv4, serverAddr, routerAddr, clientAddr; // ipv4?
  struct ifreq ifr; // ifr?
  void *tmp; // tmp?
  memset (&ifr, 0, sizeof (ifr));


  // IP header
  iphdr.ip_hl = 5;
  iphdr.ip_v = 4;
  iphdr.ip_tos = 0;
  iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN);
  iphdr.ip_id = htons (0);
  iphdr.ip_off = 0;
  iphdr.ip_ttl = 1;
  iphdr.ip_p = IPPROTO_ICMP;
  iphdr.ip_src.s_addr=inet_addr("192.168.81.128");
  iphdr.ip_dst.s_addr=inet_addr(argv[1]);
  iphdr.ip_sum = 0;
  iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN);

  // ICMP header
  icmphdr.icmp_type = ICMP_ECHO;
  icmphdr.icmp_code = 0;
  icmphdr.icmp_id = htons (1000);
  icmphdr.icmp_seq = htons (0);
  icmphdr.icmp_cksum = 0;
  icmphdr.icmp_cksum = checksum ((uint16_t *) &icmphdr, ICMP_HDRLEN);

  // set IP packet(IP Header, ICMP Header, ICMP Data)
  memcpy (packet, &iphdr, IP4_HDRLEN);
  memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN);

  // set Destination address
  memset (&serverAddr, 0, sizeof (struct sockaddr_in)); // about destination(server). use for bind
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_addr.s_addr = iphdr.ip_dst.s_addr;



  // Submit request for a raw socket descriptor.
  if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    perror ("socket() failed ");
    exit (EXIT_FAILURE);
  }

  // Set flag so socket expects us to provide IPv4 header.
  if (setsockopt (sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
    perror ("setsockopt() failed to set IP_HDRINCL ");
    exit (EXIT_FAILURE);
  }

  // Bind socket to interface index.



  // send and receive
  printf("send with ttl 1\n");
  if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN, 0, (struct sockaddr *) &serverAddr, sizeof (struct sockaddr)) < 0)  {
      perror ("sendto() failed ");
      exit (EXIT_FAILURE);
  }
  printf("after send\n");

  int addrSize = sizeof(routerAddr);
  char buff[1000];
  printf("before receive\n");
  recvfrom(sd, buff, 1000, 0, (struct sockaddr*)&routerAddr, &addrSize);
  printf("after receive\n");


  printf("close(sd)!\n");

  close (sd);

  // Free allocated memory.

  return (EXIT_SUCCESS);
}

uint16_t checksum (uint16_t *hdr, int hdrlen)
{
    uint32_t sum = 0;
    int n;
    for(n=0; n<hdrlen/2; n++)
        sum += hdr[n];

    sum = (sum&0xFFFF) + (sum>>16);
    sum = ~sum;

    return sum;
}
多谢各位


另外,我正在使用vmware来使用ubuntu。我用的是NAT

您确实需要将套接字绑定到一个地址。使用SO_BINDTODEVICE套接字选项。这看起来像是在“将套接字绑定到接口索引”下,您当前什么都没有…链接显示错误,您没有访问此服务器“”的权限。参考#24.ccc1bbcb.1431016227.15a29dd1感谢您的回答!我从其他人的密码开始。因此,一些评论可能与我的课程目标不符。我知道sendto()函数是自动绑定的。(我从昨天开始学习socket编程。)我不太了解这一点,但我在其他网站上看到过。我也不能保证这是真的。)我正在查找SO_BINDTODEVICE,但我不能清楚地理解它。人们通过“setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,device,sizeof(device));”来使用它,但我无法理解什么是设备(看起来像设备的名称“eth1”,但我不知道它是什么意思)和SOL_SOCKET是什么。这实际上是您正在测试的代码,是您的代码吗?上传代码只需将其粘贴到编辑框中即可。如果你实际上找不到你的代码,当你得到一个答案时,你可能会在修复它时遇到问题。
send with ttl 1
after send
before receive