如何使用套接字地址获取自己的IP地址?(How to get its own IP address

2019-08-21 02:43发布

我想我的程序在启动计算机的IP地址,才能够然后将它发送到客户端,但我总是0.0.0.1而不是真正的IP地址(如127.0.0.1例如)。

我目前能够得到的端口,而不是IP地址。

我怎么才能得到它?

最好的解决办法是能够用得到它sockaddr_in 。 下面是目前我在做什么:

int open_connection(char* ip, int* port)
{
  int                   sock;
  struct sockaddr_in    sin;
  socklen_t             len;
  int                   i;

  i = 0;
  len = sizeof(sin);
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    return (-1);
  bzero(&sin, sizeof(struct sockaddr_in));
  sin.sin_family = AF_INET;
  if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0)
    perror("Error on bind");
  if (getsockname(sock, (struct sockaddr *)&sin, &len) != 0)
    perror("Error on getsockname");
  strcpy(ip, inet_ntoa(sin.sin_addr)); // IP = 0.0.0.0
  *port = sin.sin_port;
  return (sock);
}

编辑:我明白我要与我的想法错了。 所以我的问题是:什么是让你自己的IP地址的最佳方式?

Answer 1:

当您bind()套接字为0.0.0.0,即打电话时是唯一的IP套接字已可用getsockname() 这意味着套接字绑定到所有的本地接口。 为了从插座获取特定的IP,它必须绑定到特定IP。

使用套接字API来获取机器的本地IP(s)是错误的做法呢。 一个常见的错误是使用gethostname()gethostbyname()getaddrinfo()获取本地IP列表。 通常这样的作品,但它有一些隐藏的陷阱,可能会导致虚假信息的,但人们往往会忽略这一事实,或者甚至不知道它摆在首位(我不知道它好几年了,但后来我学会更好)。

取而代之的是,你真的应该使用特定平台的API用于枚举本地网络接口。 这将提供更可靠的信息。 Windows有GetAdaptersInfo()GetAdaptersAddresses() 其他平台有getifaddrs() 这些会告诉你什么地方IP可用。 然后,您可以bind()的插座为0.0.0.0,以便接受任何这些IP地址的客户端,或bind()一个特定的IP接受客户仅在IP。



Answer 2:

套接字API允许你列举分配给您的网络接口的IP地址,但它不会告诉你“真正的IP”是什么,如果你是从一个路由器后面连接到互联网。

要知道它的唯一方法是通过询问外面有人。 那像的FileZilla FTP Server的服务器是如何做到这一点。 他们指导您将URL配置为“ip.php”脚本像这样一个在服务器的设置,使其可以要求互联网什么的公网IP地址,在被动模式下使用。

您也可以考虑使用STUN ,广泛应用于VoIP的协议来发现公网IP。



Answer 3:

你可以调用的ioctl(袜子,SIOCGIFADDR,ADR)

见netdevice(7)



Answer 4:

@Remy Lebeau的回答我写返回当前机器的地址的功能。 我只在MacOS海伊谢拉测试这一点。

interfaec可之间的任何lo0en0 ,等等。

ipVersionAF_INETAF_INET6

long int getInternalAddress(char* interface, sa_family_t ipVersion)
{
  struct ifaddrs *ifaddrHead, *ifaddr;
  /* int_8 */
  sa_family_t family;
  int n;
  char *interfaceName;

  if (getifaddrs(&ifaddrHead) != 0)
  {
    fprintf(stderr, "ifaddrs error");
  }

  /* iterate through address list */
  for (ifaddr = ifaddrHead, n = 0; ifaddr != NULL; ifaddr = ifaddr->ifa_next, n++)
  {
    family = ifaddr->ifa_addr->sa_family;
    interfaceName = ifaddr->ifa_name;

    if (!family || family != ipVersion || strcmp(interfaceName, interface)) continue;

    struct sockaddr *addr = ifaddr->ifa_addr;
    struct sockaddr_in* addr_in = (struct sockaddr_in*) addr;
    long int address = addr_in->sin_addr.s_addr;

    freeifaddrs(ifaddrHead);

    return address;
  }

  freeifaddrs(ifaddrHead);

  return 0;
}

要使用它,

int main()
{
  long int address = getInternalAddress((char*) &"en0", AF_INET);
  printf("%li\n", address);

  return 0;
}

我仍然在C初学者,如果有什么错误,请告诉我。



文章来源: How to get its own IP address with a socket address?