Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 11 Netzwerkprogrammierung
  gp 11.1 Einführung
  gp 11.2 Aufbau von Netzwerken
    gp 11.2.1 ISO/OSI und TCP/IP – Referenzmodell
    gp 11.2.2 Das World Wide Web (Internet)
  gp 11.3 TCP/IP – Aufbau und Struktur
    gp 11.3.1 Netzwerkschicht (Datenübertragung)
    gp 11.3.2 Internetschicht
    gp 11.3.3 Transportschicht (TCP, UDP)
    gp 11.3.4 Anwendungsschicht
  gp 11.4 TCP Socket
  gp 11.5 Kommunikationsmodell
  gp 11.6 Grundlegende Funktionen zum Zugriff auf die Socket-Schnittstelle
    gp 11.6.1 Ein Socket anlegen – socket()
    gp 11.6.2 Verbindungsaufbau – connect()
    gp 11.6.3 Socket mit einer Adresse verknüpfen – bind()
    gp 11.6.4 Auf Verbindungen warten – listen() und accept()
    gp 11.6.5 Senden und Empfangen von Daten (1) – write() und read()
    gp 11.6.6 Senden und Empfangen von Daten (2) – send() und recv()
    gp 11.6.7 Verbindung schließen – close()
  gp 11.7 Aufbau eines Clientprogramms
    gp 11.7.1 Zusammenfassung: Clientanwendung und Quellcode
  gp 11.8 Aufbau des Serverprogramms
    gp 11.8.1 Zusammenfassung: Serveranwendung und Quellcode
  gp 11.9 IP-Adressen konvertieren, manipulieren und extrahieren
    gp 11.9.1 inet_aton(), inet_pton() und inet_addr()
    gp 11.9.2 inet_ntoa() und inet_ntop()
    gp 11.9.3 inet_network()
    gp 11.9.4 inet_netof()
    gp 11.9.5 inet_lnaof()
    gp 11.9.6 inet_makeaddr()
  gp 11.10 Namen und IP-Adressen umwandeln
    gp 11.10.1 Name-Server
    gp 11.10.2 Informationen zum Rechner im Netz – gethostbyname und gethostbyaddr
    gp 11.10.3 Service-Informationen – getservbyname() und getservbyport()
  gp 11.11 Der Puffer
  gp 11.12 Standard-E/A-Funktionen verwenden
    gp 11.12.1 Pufferung von Standard-E/A-Funktionen
  gp 11.13 Parallele Server
  gp 11.14 Syncrones Multiplexing – select()
  gp 11.15 POSIX-Threads und Netzwerkprogrammierung
  gp 11.16 Optionen für Sockets setzen bzw. erfragen
    gp 11.16.1 setsockopt()
    gp 11.16.2 getsockopt()
    gp 11.16.3 Socket-Optionen
  gp 11.17 UDP
    gp 11.17.1 Clientanwendung
    gp 11.17.2 Serveranwendung
    gp 11.17.3 recvfrom() und sendto()
    gp 11.17.4 bind() verwenden oder weglassen
  gp 11.18 UNIX-Domain-Sockets (IPC)
    gp 11.18.1 Die Adressstruktur von UNIX-Domain-Sockets
    gp 11.18.2 Lokale Sockets erzeugen – socketpair()
  gp 11.19 Multicast-Socket
    gp 11.19.1 Anwendungsgebiete von Multicast-Verbindungen
  gp 11.20 Nicht blockierende I/O-Sockets
  gp 11.21 Etwas zu Streams und TLI, Raw Socket, XTI
    gp 11.21.1 Raw Socket
    gp 11.21.2 TLI und XTI
    gp 11.21.3 RPC (Remote Procedure Call)
  gp 11.22 IPv4 und IPv6
    gp 11.22.1 IPv6 – ein wenig genauer
  gp 11.23 Netzwerksoftware nach IPv6 portieren
    gp 11.23.1 Konstanten
    gp 11.23.2 Strukturen
    gp 11.23.3 Funktionen
  gp 11.24 Sicherheit und Verschlüsselung


Rheinwerk Computing

11.9 IP-Adressen konvertieren, manipulieren und extrahieren  downtop

Bevor Sie noch tiefer in die Welt der Netzwerkprogrammierung einsteigen können, benötigen Sie noch das Wissen einiger Funktionen, die auf den vorherigen Seiten noch nicht oder ungenügend behandelt wurden.


Rheinwerk Computing

11.9.1 inet_aton(), inet_pton() und inet_addr()  downtop

Mit den Funktionen inet_aton() und inet_addr() konvertieren Sie den String in der punktierten Dezimaldarstellung (z. B. »127.0.0.1«) in eine 32-Bit-Internet-Adresse. Die Funktion inet_addr() ist veraltet und wird deshalb hier nicht mehr behandelt. Die Syntax zu inet_aton():

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *ptr, struct in_addr *inp);

Hiermit wird aus der punktierten Stringdarstellung ptr eine 32-Bit-Adresse konvertiert. Der Wert dieser 32-Bit-Adresse befindet sich anschließend in der Adresse der Struktur in_addr. Diese Struktur ist ja auch Teil der Struktur, die zur IP-Socket-Adresse verwendet wird. Hier nochmals die Struktur zur Erinnerung:

struct sockaddr_in {
  /* Adressfamilie normalerweise AF_INET  */
  short int          sin_family;
  /* Port der Verbindung                  */
  unsigned short int sin_port;
  /* Adresse, zu der verbunden werden soll */
  struct in_addr     sin_addr;
  /* Fuelldaten, um auf 14 Bytes zu kommen */
  unsigned char      sin_zero[8]; 
};

Die Struktur in_addr, die von vielen der folgenden Funktionen ebenfalls verwendet wird, ist in der Headerdatei <netinet/in.h> folgendermaßen definiert:

struct in_addr{
     unsigned long int sin_addr;
}

Bei einem Fehler gibt die Funktion inet_aton() 0, ansonsten bei Erfolg einen Wert ungleich 0 zurück.

Zukunftsweisend ist hier noch die Funktion inet_pton(), die im Gegensatz zu inet_aton() auch noch andere Adressen als IPv4 wandelt:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
int inet_pton(int af, const char *src, void *dst);

Für af geben Sie die Adressfamilie wie schon bei socket() an, für src den String der punktierten Darstellung und mit dst einen Zeiger auf die Zielstruktur, die je nach Adressfamilie variiert. In der Praxis:

struct in_addr addr;
inet_pton(AF_INET, "127.0.0.1", &addr);

Rheinwerk Computing

11.9.2 inet_ntoa() und inet_ntop()  downtop

Soll im Gegenzug aus der 32-Bit-Darstellung der IP-Adresse wieder eine punktierte Darstellung zum String gemacht werden, steht Ihnen die Funktion inet_ntoa() zur Verfügung:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa( struct in_addr in );

Damit wird die übergebene 32-Bit-Adresse als Parameter, die als network-byte-order vorliegen muss, in eine punktierte Dezimaldarstellung als String konvertiert. Der String wird als Rückgabewert der Funktionen in einem statischen Puffer abgelegt. Bei einem Fehler wird NULL zurückgegeben.

Die Funktion inet_ntoa() ist nicht thread-safe, da sie einen statischen Puffer verwendet! Daher – wieder die zukunftssicherere Alternative – inet_ntop():

#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
const char *inet_ntop( int af, const void *src,
                       char *dst, socklen_t cnt );

Für af geben Sie wieder die Adressfamilie wie schon bei socket() an, für src die 32-Bit-Darstellung der IP-Adresse und mit dst einen Zeiger auf einen String, in dem der konvertierte Wert mit cnt Bytes kopiert wird. In der Praxis:

char buf[16];
...
inet_ntop(AF_INET, &addr, buf, 16);

Rheinwerk Computing

11.9.3 inet_network()  downtop

Um aus einer IP-Adresse (punktierte Dezimaldarstellung in Form eines Strings) eine Netzwerknummer zu machen, können Sie die Funktion inet_network() verwenden:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t int inet_network( const char * ptr );

Damit konvertieren Sie die punktierte String-Dezimaldarstellung der IP-Adresse ptr in die Netzwerknummer. Diese Netzwerknummer wird bei Erfolg als Rückgabewert von inet_network() in host-byte-order zurückgegeben. Bei einem Fehler wird -1 zurückgegeben.


Netzwerknummer ist der Netzanteil einer IP-Adresse. Die IP-Adressen werden wiederum in eine IP-Netzklasse unterteilt. Dies ist eine Unterteilung in einen Netz- und einen Host-Anteil. Die Netzklasse ist abhängig von der Anzahl der Computer, die z. B. in einer Firma an das Internet angeschlossen sind. Generell werden in der Praxis die Klassen A, B und C verwendet. Die Klasse C teilt die Adresse in N.N.N.H (N – Netz, H – Host) und enthält so 255 Adressen. Mit der Klasse B sind 255 mal 255 Adressen möglich, weil zwei Byte für den Hostanteil verwendet werden (N.N.H.H). Und die Klasse A wird kaum noch verwendet, da sie mit 16581375 adressierbaren Computern (N.H.H.H) ein sehr großes Stück aus dem knappen Adressraum herausschneidet.



Rheinwerk Computing

11.9.4 inet_netof()  downtop

Um aus einer nummerischen 32-Bit-IP-Adresse eine Netzwerknummer zu machen, können Sie die Funktion inet_netof() verwenden:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t int inet_netof( struct in_addr in );

Damit konvertieren Sie die nummerische 32-Bit-Darstellung der IP-Adresse, die als Parameter angegeben wird, in die Netzwerknummer. Diese Netzwerknummer wird bei Erfolg als Rückgabewert von inet_netof() in host-byte-order zurückgegeben. Bei einem Fehler wird -1 zurückgegeben.


Rheinwerk Computing

11.9.5 inet_lnaof()  downtop

Um den lokalen Teil aus einer nummerischen 32-Bit-IP-Adresse zu extrahieren, steht Ihnen die Funktion inet_lnaof() zur Verfügung:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_lnaof( struct in_addr in );

Damit ermitteln Sie die Adresse des lokalen Teils (z. B. 127.0.0.1 -> der lokale Teil = 0.0.0.1) des Rechners. Die Funktion gibt diesen Wert in Form eines 32-Bit-Wertes in host-byte-order zurück. Bei Fehler wird -1 zurückgegeben.


Rheinwerk Computing

11.9.6 inet_makeaddr()  toptop

Um aus dem lokalen Teil eines Rechners und einer Netzwerknummer eine richtige nummerische IP-Adresse zu machen, können Sie die Funktion inet_makeaddr() verwenden:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
struct in_addr inet_makeaddr( int net, int host );

Damit wird aus der Netzwerknummer net und der Adresse des lokalen Rechnerteils (host) eine vollständige nummerische 32-Bit-IP-Adresse zurückgeliefert. Die Werte net und host müssen in host-byte-order übergeben werden.

Hierzu ein Listing mit allen Funktionen bei der Ausführung:

/* addr.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
static void ip_adressen (const char *ip_addr) {
  struct in_addr ip;
  char *ip_str;
  if (inet_aton (ip_addr, &ip) == 0)
    return;
  printf ("\n  *** Gesamtteil der IP-Adresse *** \n");
  printf ("IP-Adresse (argv[1])                : %s\n",
     ip_addr);
  printf ("IP-Adresse als 32-Bit Wert - inet_aton() : %d\n",
     ip.s_addr);
  ip_str = inet_ntoa (ip);
  if (ip_str == NULL)
    return;
  printf ("IP-Adresse String mit inet_ntoa()     : %s\n",
     ip_str);
}
static void ip_netzwerk (const char *ip_addr) {
  struct in_addr ip, net_ip;
  unsigned long int net, net_num;
  if (inet_aton (ip_addr, &ip) == 0)
    return;
  net = inet_netof (ip);
  if (net <= 0)
    return;
  /* Netzwerkteil */
  printf ("\n  *** Netzwerkteil der IP-Adresse *** \n");
  printf ("Netzwerknummer der IP-Adresse mit "
          "inet_netof()  : %lu\n", net);
  net_ip.s_addr = net_num = ntohl (inet_netof (ip) << 8);
  printf ("--->%s", inet_ntoa (net_ip));
  printf ("--> (als 32-Bit-Wert) : %ld\n", net_num);
  net_ip = inet_makeaddr (htonl (net_num), 0);
  printf ("inet_makeaddr()->(als 32-Bit-Wert) : %d\n",
     net_ip.s_addr);
}
static void ip_lokal (const char *ip_addr) {
  struct in_addr ip, lokal_ip;
  unsigned long int lokal_num;
  if (inet_aton (ip_addr, &ip) == 0)
    return;
  printf ("\n  *** Lokaler Teil der IP-Adresse *** \n");
  lokal_ip.s_addr = lokal_num = ntohl (inet_lnaof (ip));
  printf ("--->%s", inet_ntoa (lokal_ip));
  printf ("--> (als 32-Bit-Wert) : %ld\n", lokal_num);
  lokal_ip = inet_makeaddr (0, htonl (lokal_num));
  printf ("inet_makeaddr()->(als 32-Bit-Wert) : %d\n",
     lokal_ip.s_addr);
}
static void ip_zusammen (const char *ip_addr) {
  struct in_addr ip, lokal_ip, net_ip, zusammen_ip;
  unsigned long int lokal_num, net_num;
  if (inet_aton (ip_addr, &ip) == 0)
    return;
  printf ("\n  *** Lokale Teile und Netzwerkteil "
          "zusammensetzen *** \n");
  lokal_ip.s_addr = lokal_num = ntohl (inet_lnaof (ip));
  printf ("Lokaler Teil: ");
  printf ("%20s = ", inet_ntoa (lokal_ip));
  printf ("(als 32-Bit-Wert) : %ld\n", lokal_num);
  printf ("Netzwerkteil: ");
  net_ip.s_addr = net_num = ntohl (inet_netof (ip) << 8);
  printf ("%20s = ", inet_ntoa (net_ip));
  printf ("(als 32-Bit-Wert) : %ld\n", net_num);
  zusammen_ip=inet_makeaddr( htonl (net_num),
                             htonl (lokal_num));
  printf("Alles wieder mit inet_makeaddr zusammengefügt: ");
  printf ("\n%s = %d\n", inet_ntoa (zusammen_ip),
     zusammen_ip.s_addr);
}
int main (int argc, char **argv) {
  char *ptr;
  if (argc != 2)
     printf ("Verwendung %s IP-Adresse\n", *argv);
  else {
     ptr = argv[1];
     ip_adressen (ptr);
     ip_netzwerk (ptr);
     ip_lokal (ptr);
     ip_zusammen (ptr);
  }
  return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o addr addr.c
$ ./addr 213.131.254.130
 *** Gesamtteil der IP-Adresse ***
IP-Adresse (argv[1])                      : 213.131.254.130
IP-Adresse als 32-Bit Wert mit inet_aton() : 2197717973
IP-Adresse String mit inet_ntoa()         : 213.131.254.130
 *** Netzwerkteil der IP-Adresse ***
Netzwerknummer der IP-Adresse mit inet_netof()  : 13992958
--->213.131.254.0--> (als 32-Bit-Wert) : 16679893
mit inet_makeaddr() --> (als 32-Bit-Wert) : 16679893
 *** Lokaler Teil der IP-Adresse ***
--->0.0.0.130--> (als 32-Bit-Wert) : 2181038080
mit inet_makeaddr() --> (als 32-Bit-Wert) : 2181038080
 *** Lokale Teile und Netzwerkteil zusammensetzen ***
Lokaler Teil:            0.0.0.130 = (als 32-Bit-Wert) : 2181038080
Netzwerkteil:        213.131.254.0 = (als 32-Bit-Wert) : 16679893
Alles wieder mit inet_makeaddr() zusammengefügt:
213.131.254.130 = 2197717973
 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern