getaddrinfo使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mayue_web/article/details/98102013

getaddrinfo根据域名获取IP等信息。

头文件

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

函数原型

int getaddrinfo(const char *node, const char *service,
                       const struct addrinfo *hints,
                       struct addrinfo **res);

void freeaddrinfo(struct addrinfo *res);

const char *gai_strerror(int errcode);

注意在使用getaddrinfo时,const struct addrinfo *hints优先配置SOCK_STREAM域,SOCK_DGRAM有失败的情况。

addrinfo 结构体定义

struct addrinfo {
	int     ai_flags;
	int     ai_family;
	int     ai_socktype;
	int     ai_protocol;
	size_t  ai_addrlen;
	struct sockaddr *ai_addr;
	char   *ai_canonname;
	struct addrinfo *ai_next;
 };

示例1:只取第一个IP地址

#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>//结构体addrinfo, in_addr
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

int main(){
  char* hostname = "www.cnblogs.com";//博客园的网址,返回实际IP地址
  addrinfo hints, *res;
  in_addr addr;
  int err;

  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_family = AF_INET;

  if((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0){
    printf("error %d : %s\n", err, gai_strerror(err));
    return 1;
  }
  addr.s_addr = ((sockaddr_in*)(res->ai_addr))->sin_addr.s_addr;
  printf("ip addresss: %s\n", inet_ntoa(addr));//博客园的网址,返回实际IP地址
  
  freeaddrinfo(res);

  return 0;
}

示例2:显示所有域名查找到的所有IP地址

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>//结构体addrinfo, in_addr
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

int main(int argc, char **argv){
  char *hostname;
  struct addrinfo hints,*result, *rp;
  int err;
  in_addr addr;

  //没有输入域名时,博客园的网址,返回实际IP地址
  hostname = argc < 2 ? (char *)"www.cnblogs.com" : argv[1];

  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_family = AF_INET;


  if((err = getaddrinfo(hostname, NULL, &hints, &result)) != 0){
    printf("error %d : %s\n", err, gai_strerror(err));
    return 1;
  }


  for (rp = result; rp != NULL; rp = rp->ai_next) {
    addr.s_addr = ((sockaddr_in*)(rp->ai_addr))->sin_addr.s_addr;
    printf("ip addresss: %s\n", inet_ntoa(addr));
   }

  freeaddrinfo(result);

  return 0;
}

一遍都会输出两个IP地址,如www.baidu.com

示例3:

Server program:

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>

#define BUF_SIZE 500

int main(int argc, char *argv[])
{
   struct addrinfo hints;
   struct addrinfo *result, *rp;
   int sfd, s;
   struct sockaddr_storage peer_addr;
   socklen_t peer_addr_len;
   ssize_t nread;
   char buf[BUF_SIZE];

   if (argc != 2) {
       fprintf(stderr, "Usage: %s port\n", argv[0]);
       exit(EXIT_FAILURE);
   }

   memset(&hints, 0, sizeof(struct addrinfo));
   hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
   hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
   hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
   hints.ai_protocol = 0;          /* Any protocol */
   hints.ai_canonname = NULL;
   hints.ai_addr = NULL;
   hints.ai_next = NULL;

   s = getaddrinfo(NULL, argv[1], &hints, &result);
   if (s != 0) {
       fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
       exit(EXIT_FAILURE);
   }

   /* getaddrinfo() returns a list of address structures.
      Try each address until we successfully bind(2).
      If socket(2) (or bind(2)) fails, we (close the socket
      and) try the next address. */

   for (rp = result; rp != NULL; rp = rp->ai_next) {
       sfd = socket(rp->ai_family, rp->ai_socktype,
               rp->ai_protocol);
       if (sfd == -1)
           continue;

       if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
           break;                  /* Success */

       close(sfd);
   }

   if (rp == NULL) {               /* No address succeeded */
       fprintf(stderr, "Could not bind\n");
       exit(EXIT_FAILURE);
   }

   freeaddrinfo(result);           /* No longer needed */

   /* Read datagrams and echo them back to sender */
   for (;;) {
       peer_addr_len = sizeof(struct sockaddr_storage);
       nread = recvfrom(sfd, buf, BUF_SIZE, 0,
               (struct sockaddr *) &peer_addr, &peer_addr_len);
       if (nread == -1)
           continue;               /* Ignore failed request */

       char host[NI_MAXHOST], service[NI_MAXSERV];

       s = getnameinfo((struct sockaddr *) &peer_addr,
                       peer_addr_len, host, NI_MAXHOST,
                       service, NI_MAXSERV, NI_NUMERICSERV);
       if (s == 0)
           printf("Received %zd bytes from %s:%s\n",
                   nread, host, service);
       else
           fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));

       if (sendto(sfd, buf, nread, 0,
                   (struct sockaddr *) &peer_addr,
                   peer_addr_len) != nread)
           fprintf(stderr, "Error sending response\n");
   }
}

Client program

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define BUF_SIZE 500

int
main(int argc, char *argv[])
{
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int sfd, s, j;
    size_t len;
    ssize_t nread;
    char buf[BUF_SIZE];

    if (argc < 3) {
        fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Obtain address(es) matching host/port */

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
    hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
    hints.ai_flags = 0;
    hints.ai_protocol = 0;          /* Any protocol */

    s = getaddrinfo(argv[1], argv[2], &hints, &result);
    if (s != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        exit(EXIT_FAILURE);
    }

    /* getaddrinfo() returns a list of address structures.
       Try each address until we successfully connect(2).
       If socket(2) (or connect(2)) fails, we (close the socket
       and) try the next address. */

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sfd = socket(rp->ai_family, rp->ai_socktype,
                     rp->ai_protocol);
        if (sfd == -1)
            continue;

        if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
            break;                  /* Success */

        close(sfd);
    }

    if (rp == NULL) {               /* No address succeeded */
        fprintf(stderr, "Could not connect\n");
        exit(EXIT_FAILURE);
    }

    freeaddrinfo(result);           /* No longer needed */

    /* Send remaining command-line arguments as separate
       datagrams, and read responses from server */

    for (j = 3; j < argc; j++) {
        len = strlen(argv[j]) + 1;
                /* +1 for terminating null byte */

        if (len > BUF_SIZE) {
            fprintf(stderr,
                    "Ignoring long message in argument %d\n", j);
            continue;
        }

        if (write(sfd, argv[j], len) != len) {
            fprintf(stderr, "partial/failed write\n");
            exit(EXIT_FAILURE);
        }

        nread = read(sfd, buf, BUF_SIZE);
        if (nread == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }

        printf("Received %zd bytes: %s\n", nread, buf);
    }

    exit(EXIT_SUCCESS);
}

getaddrinfo函数ipv6的应用
https://blog.csdn.net/u012654882/article/details/51832768

参考资料
https://www.cnblogs.com/xiaoshiwang/p/9763825.html
http://www.man7.org/linux/man-pages/man3/getaddrinfo.3.html
https://blog.csdn.net/fanx021/article/details/80549945
https://blog.csdn.net/u011028408/article/details/84067040
https://blog.csdn.net/jctian000/article/details/81912346

展开阅读全文

关于getaddrinfo api源文件的编译

01-31

在msdn上查了此函数,我想编译,运行一下它的例程可是怎么都不成功。rn目前编译已成功,连接仍出现如下问题:rnrn--------------------Configuration: ddd - Win32 Debug--------------------rnLinking...rndddd.obj : error LNK2001: unresolved external symbol __imp__freeaddrinfo@4rndddd.obj : error LNK2001: unresolved external symbol __imp__getaddrinfo@16rnDebug/ddd.exe : fatal error LNK1120: 2 unresolved externalsrn执行 link.exe 时出错.rnrnddd.exe - 1 error(s), 0 warning(s)rnrnrn源代码如下:rn#include rn#include rn#include rn#include rnrn//link with Ws2_32.librnrnint __cdecl main(int argc, char **argv)rnrnrn //-----------------------------------------rn // Declare and initialize variablesrn WSADATA wsaData;rn int iResult;rnrn DWORD dwRetval;rnrn int i = 1;rn rn char *port = "27015";rnrn struct addrinfo *result = NULL;rn struct addrinfo *ptr = NULL;rn struct addrinfo hints;rnrnrn // Validate the parametersrn if (argc != 2) rn printf("usage: %s \n", argv[0]);rn printf(" getaddrinfo provides protocol-independent translation\n");rn printf( " from an ANSI host name to an IP address\n");rn printf(" %s www.contoso.com\n", argv[0]);rn return 1;rn rn // Initialize Winsockrn iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);rn if (iResult != 0) rn printf("WSAStartup failed: %d\n", iResult);rn return 1;rn rnrn //--------------------------------rn // Setup the hints address info structurern // which is passed to the getaddrinfo() functionrn ZeroMemory( &hints, sizeof(hints) );rn hints.ai_family = AF_UNSPEC;rn hints.ai_socktype = SOCK_STREAM;rn hints.ai_protocol = IPPROTO_TCP;rnrnrn//--------------------------------rn// Call getaddrinfo(). If the call succeeds,rn// the result variable will hold a linked listrn// of addrinfo structures containing responsern// informationrn dwRetval = getaddrinfo(argv[1], port, &hints, &result);rn if ( dwRetval != 0 ) rn printf("getaddrinfo failed with error: %d\n", dwRetval);rn WSACleanup();rn return 1;rn rnrn printf("getaddrinfo returned success\n");rn rn // Retrieve each address and print out the hex bytesrn for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) rnrn printf("getaddrinfo response %d\n", i++);rn printf("\tFlags: 0x%x\n", ptr->ai_flags);rn printf("\tFamily: ");rn switch (ptr->ai_family) rn case AF_UNSPEC:rn printf("Unspecified\n");rn break;rn case AF_INET:rn printf("AF_INET (IPv4)\n");rn break;rn case AF_INET6:rn printf("AF_INET6 (IPv6)\n");rn break;rn case AF_NETBIOS:rn printf("AF_NETBIOS (NetBIOS)\n");rn break;rn default:rn printf("Other %ld\n", ptr->ai_family);rn break;rn rn printf("\tSocket type: ");rn switch (ptr->ai_socktype) rn case 0:rn printf("Unspecified\n");rn break;rn case SOCK_STREAM:rn printf("SOCK_STREAM (stream)\n");rn break;rn case SOCK_DGRAM:rn printf("SOCK_DGRAM (datagram) \n");rn break;rn case SOCK_RAW:rn printf("SOCK_RAW (raw) \n");rn break;rn case SOCK_RDM:rn printf("SOCK_RDM (reliable message datagram)\n");rn break;rn case SOCK_SEQPACKET:rn printf("SOCK_SEQPACKET (pseudo-stream packet)\n");rn break;rn default:rn printf("Other %ld\n", ptr->ai_socktype);rn break;rn rn printf("\tProtocol: ");rn switch (ptr->ai_protocol) rn case 0:rn printf("Unspecified\n");rn break;rn case IPPROTO_TCP:rn printf("IPPROTO_TCP (TCP)\n");rn break;rn case IPPROTO_UDP:rn printf("IPPROTO_UDP (UDP) \n");rn break;rn default:rn printf("Other %ld\n", ptr->ai_protocol);rn break;rn rn printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);rn printf("\tCanonical name: %s\n", ptr->ai_canonname);rn rnrn freeaddrinfo(result);rn WSACleanup();rnrn return 0;rnrnrnrn另外我补充几点,我用的系统是xp_sp3,开发工具是vc6,rn而且在连接器中已经加了Ws2_32.lib.rnrn希望大牛相助。。。先谢谢! 论坛

没有更多推荐了,返回首页