【问题标题】:local IP after gethostbyname()gethostbyname() 后的本地 IP
【发布时间】:2011-06-27 09:14:28
【问题描述】:

如何在使用sendto() 之前获取本地IP 地址,该地址将用于传输到远程主机?

如果我理解正确的话,应该在gethostbyname(remoteHostname) 通话之后就已经知道了。

我需要这个来在传输的数据包中包含本地 IP(127.0.0.1 没有意义)。使用 UDP。

【问题讨论】:

  • 为什么需要本地IP?您的操作系统的 IP 堆栈将插入本地和正确的源地址。您通常需要远程 IP 地址,因此您知道将数据包发送到哪个地址。
  • 这是协议要求。它就像 SNMP 陷阱中的代理 IP。

标签: c sockets network-programming


【解决方案1】:

尝试在已连接的 UDP 套接字上调用 getsockname(2);堆栈需要执行大量路由来连接套接字,足以知道一旦发送或接收数据包将使用哪个本地地址。

【讨论】:

  • 我希望通过gethostname获取本地IP的路由就足够了。消息本身类似于陷阱,因此套接字在传输之前没有“连接”(因为它可能是第一次传输)。
  • @Noros 没关系,你可以在发送第一条消息之前调用 connect() 。对于 UDP,connect() 只是本地机器/您的进程的内部。不与远程方交换任何消息。 (但如果您需要发送到许多不同的远程地址,那么您必须创建一个新套接字并为每个远程地址连接它 - 除非您绝对知道您的机器将只有 1 个 IP 地址)
【解决方案2】:

您可以先在套接字上调用 connect()。 UDP当然不是面向连接的,但是connect只会注册套接字以仅发送到给定的远程IP地址,因此您可以例如只需使用 send() 而不是 sendto()

但是,这允许您在套接字上调用 getsockname(),并且至少在 Linux 下这将获取套接字使用的本地地址。这是一个示例,您可以在此处提取 print_local_addr() 中的信息并在 SNMP 陷阱中使用该信息。 (仅当您也需要固定源端口时才需要调用 bind())

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>


void diep(char *s)
{
  perror(s);
  exit(1);
}

void print_local_addr(int s)
{
    struct sockaddr_in my_addr;
    socklen_t len = sizeof my_addr;
    if(getsockname(s,(struct sockaddr*)&my_addr,&len) == -1)
      diep("getsockname");
    //print the local address of the socket that will be used when
    //sending datagrams to the "connected" peer.
    printf("local addr %s:%u\n",inet_ntoa(my_addr.sin_addr),ntohs(my_addr.sin_port));
}

int main(void)
{
  struct sockaddr_in si_me, si_other;
  int s;

  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    diep("socket");

  memset(&si_me, 0, sizeof(si_me));
  memset(&si_other, 0, sizeof(si_me));
  //bind to local port 4567
  si_me.sin_family = AF_INET;
  si_me.sin_port = htons(4567);
  si_me.sin_addr.s_addr = htonl(INADDR_ANY);

  //"connect" google's DNS server at 8.8.8.8 , port 4567
  si_other.sin_family = AF_INET;
  si_other.sin_port = htons(4567);
  si_other.sin_addr.s_addr = inet_addr("8.8.8.8");
  if(connect(s,(struct sockaddr*)&si_other,sizeof si_other) == -1)
    diep("connect");
  print_local_addr(s);
  close(s);
  return 0;
}

【讨论】:

  • 优秀的小程序。谢谢。
【解决方案3】:

信息来自:http://www.suite101.com/content/socket-programming-gethostbyname-a19557

正如你所说,localhost 不起作用。相反,请先查找您的主机名,然后将其传递给 gethostbyname

char hostName[255];
gethostname(hostName, 255);

struct hostent* host_entry;
host_entry=gethostbyname(hostName);

char* localIP;
szLocalIP = inet_ntoa (*(struct in_addr*)*host_entry->h_addr_list);

如果这不合适,你也可以做一个 DNS 查找,做一个 WMI 查询,或者在注册表中查找。

【讨论】:

  • 我如何知道以这种方式找到的 IP 将用于传输到给定的远程 IP(由 gethostbyname 解析)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 2013-07-23
相关资源
最近更新 更多