next up previous contents
Next: Protokollunabhängige Adreßauflösung Up: 3.3 Anwendungsentwicklung Previous: Adreßauflösung

Protokollunabhängige Namensauflösung

Die in Arbeit befindliche Spezifikation des Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g definiert eine protokollunabhängige Funktion getaddrinfo() zur Übersetzung eines Rechnernamens in eine IP-Adresse. Die Beschreibung dieser Funktion wurde ebenfalls in [Gilligan 97] wiedergegeben:

int getaddrinfo(const char *hostname , const char *servname , const struct addrinfo *hints , struct addrinfo **res );

Im üblichen Client-Szenario, so auch im Beispiel IPv6/IPv4-TCP-Client, werden an die Funktion sowohl ein hostname als auch ein servname übergeben, die beide nicht NULL sind:

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

argv[1] und argv[2] enthalten Namen und Port des Servers.

hints wurde zuvor mit Hinweisen auf den gewünschten Socket-Typ und weiteren Flags gefüllt:

  memset(&hints, 0, sizeof(hints));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_CANONNAME;

In pai wird ein Zeiger auf eine verkettete Liste von einer oder mehreren komplettierten addrinfo-Strukturen zurückgeliefert.

Die addrinfo-Struktur ist folgendermaßen definiert:

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

  struct addrinfo {
    int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME */
    int     ai_family;    /* PF_xxx */
    int     ai_socktype;  /* SOCK_xxx */
    int     ai_protocol;  /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
    size_t  ai_addrlen;   /* length of ai_addr */
    char   *ai_canonname; /* canonical name for hostname */
    struct sockaddr  *ai_addr; /* binary address */
    struct addrinfo  *ai_next; /* next structure in linked list */
  };

Im Beispiel werden zur Verdeutlichung die einzelnen Feldinhalte ausgegeben.

Ist ai als struct addrinfo definiert, kann nach dem obigen Funktionsaufruf in dieser Weise ein Socket erzeugt werden:

  if ((sock = socket(ai->ai_family, ai->ai_socktype,
                     ai->ai_protocol)) < 0) {
    printf("socket: %s(%d)\n", strerror(errno), errno);
    continue;
  };

So kann ein Verbindungswunsch geäußert werden:

  if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
    printf("connect: %s(%d)\n", strerror(errno), errno);
    continue;
  };

Im üblichen Server-Szenario wird die getaddrinfo()-Funktion ohne Angabe des Rechnernamens im ersten Parameter aufgerufen, was der Spezifikation einer ,,Wildcard``-Adresse entspricht:

  if (result = getaddrinfo(NULL, port, &hints, pai)) {
    fprintf(stderr, "getnameinfo: %s\n", gai_strerror(result));
    exit(1);
  }

Die bind()-Funktion kann analog zur connect-Funktion verwendet werden:

  if (bind(sock, ai->ai_addr, ai->ai_addrlen)) {
    perror("bind");
    exit(1);
  }


next up previous contents
Next: Protokollunabhängige Adreßauflösung Up: 3.3 Anwendungsentwicklung Previous: Adreßauflösung
Copyright Munich Network Management Team