如何获取服务器程序的IP地址?

时间:2010-03-22 23:19:25

标签: c unix sockets

此问题与another question I just posted有关。我正准备一个简单的工作项目,并试图熟悉Unix开发环境中套接字编程的基础知识。此时,我有一些基本的服务器端代码和客户端代码设置进行通信。目前,我的客户端代码成功连接到服务器代码,服务器代码向它发送测试消息,然后退出。完善!这正是我想要完成的。现在,我正在使用用于获取有关两个环境(服务器和客户端)的信息的函数。我想获取服务器程序的IP地址。这是我目前要做的代码,但它不起作用......

int sockfd;
unsigned int len;
socklen_t sin_size;
char msg[]="test message";
char buf[MAXLEN];
int st, rv;
struct addrinfo hints, *serverinfo, *p; 
struct sockaddr_storage client;
char s[INET6_ADDRSTRLEN];
char ip[INET6_ADDRSTRLEN];

//zero struct   
memset(&hints,0,sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//get the server info
if((rv = getaddrinfo(NULL, SERVERPORT, &hints, &serverinfo ) != 0)){
  perror("getaddrinfo");
  exit(-1);
}

// loop through all the results and bind to the first we can
for( p = serverinfo; p != NULL; p = p->ai_next)
{
  //Setup the socket
  if( (sockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol )) == -1 )
  {
    perror("socket");
    continue;
  }

  //Associate a socket id with an address to which other processes can connect
  if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
    close(sockfd);
    perror("bind");
    continue;
  }

  break;
}

if( p == NULL ){
  perror("Fail to bind");
}

inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof(s));
printf("Server has TCP Port %s and IP Address %s\n", SERVERPORT, s);

并且IP的输出始终为空......

server has TCP Port 22513 and IP Address ::

我缺少什么想法?

提前感谢您的帮助!这个东西起初真的很复杂。

2 个答案:

答案 0 :(得分:2)

您的套接字可能正在侦听所有可用的接口/地址。 “::”是IPv6地址“0:0:0:0:0:0:0:0”的简写,表示该地址未指定。

这可能是因为您从getaddrinfo()请求addrinfo来侦听任何地址,并且任何支持流的协议和具有未指定地址的IPv6恰好是第一个。我对此有点不确定......

答案 1 :(得分:0)

您的代码似乎正如所写的那样正常运行,但可能与预期/意图不符。您正在打印的IP地址是正确的,因为您绑定到所有可用接口,因此服务器将能够接受任何网络接口上的传入TCP连接。

您传递给getaddrinfo()提示结构会产生以下结果:

  • AF_UNSPEC for ai_family 表示来电者应接受任何地址系列
  • ai_socktype 的SOCK_STREAM指定流套接字类型
  • ai_flags 中包含的AI_PASSIVE导致返回的地址适合用于绑定套接字以接受传入连接
    • 由于 nodename 为NULL,因此套接字地址结构的IP地址部分对于IPv4地址设置为INADDR_ANY,对于IPv6地址设置为IN6ADDR_ANY_INIT

由于IPv6地址在RFC 3484排序中的IPv4地址之前排序,getaddrinfo()返回未指定的IPv6地址(“0:0:0:0:0:0:0:0”)

在对inet_ntop()的调用中,未指定的IPv6地址可以简单地表示为“::”。


如果您正在寻找可以等同于服务器主机名的地址,您可以通过gethostname()检索机器的主机名,并将其用作节点名< / em>在您致电getaddrinfo()时。由于您为 ai_family 指定了AF_UNSPEC,因此 nodename 的有效描述性名称包括主机名。如果确实指定了特定的IP地址来代替INADDR_ANY / IN6ADDR_ANY_INIT,那么套接字将只接受通过该接口的TCP连接。