Tutorials - Winsock Tutorial Teil 2: Hostnamen auflösen

Sprachenübersicht/Programmierung/C / C++/ C#/Netzwerk

Winsock Tutorial Teil 2: Hostnamen auflösen

Diese Seite wurde 6589 mal aufgerufen.

Diese Artikel wurde als uneditierbar gepostet, und darf, wenn nicht ausdrücklich erlaubt nicht auf anderen Seiten verbreitet, oder editiert werden! Printversion

Keywords: C++ Tutorial, Winsock, programmieren, quellcode, Netzwerk, TCP/IP, Hostname auflösen

Vorwort Top



Dieses Tutorial stammt von c-worker.ch Es darf auf einer eigenen Seite veröffentlicht werden sofern es unverändert bleibt, und die Seite www.c-worker.ch als Quelle erwähnt wird. Für die Richtigkeit aller in diesem Dokument beschriebenen Angaben und für eventuelle Schäden die durch dieses Dokument entstehen könnten wird nicht gehaftet.

Hinweise:


Falls beim kompilieren einige "Neudefinition" Fehler kommen entfernt die "#include <winsock2.h>" Zeile (wurde in diesem Fall 

schon in windows.h includiert)
Falls der Compiler ADDR_ANY nicht finden kann verwendet INADDR_ANY.



Einleitung Top



Im ersten Tutorial wurde unter anderem gezeigt wie man eine Verbingung zu einem Server aufbaut. Das ganze war jedoch nicht

sehr flexibel da wir die IP des Servers in unseren Quellcode reingeschrieben haben. Besser wäre es doch wenn man die IP oder

noch besser den Hostnamen als Parameter an das Programm übergeben könnte. Und genau das werden wir hier machen. Der Client

vom letzten Tutorial (sock.c) wird hier so erweitert das man als ersten Parameter einen Hostnamen oder eine IP angeben kann,

zu welchem dann die Verbindung hergestellt wird.

Hostnamen in eine IP auflösen Top



Um einen Hostnamen in eine IP aufzulösen steht die Funktion gethostbyname() zur verfügug:

Code:


struct hostent FAR * gethostbyname (

  const char FAR * name  

);




-name: ein Hostname für den die IP herausgefunden werden soll

Als Rückgabewert liefert die Funktion einen Pointer auf eine HOSTENT Struktur, diese ist folgendermassen definiert:

Code:


struct hostent {

    char FAR *       h_name;

    char FAR * FAR * h_aliases;

    short            h_addrtype;

    short            h_length;

    char FAR * FAR * h_addr_list;

};



Dabei interessiert uns nur h_addr_list, welches eine mit 0 terminierte Liste von IP Adressen ist, und zwar in Network Byte

Order (also kein htonl() nötig).
Bei einem Fehler, oder falls die IP für den entsprechenden Hostnamen nicht gefunden werden konnte liefert die Funktion NULL

zurück.

Wir schreiben nun eine eigene Funktion die all diese Arbeit abnimmt, dabei übernimmt sie als ersten Parameter einen String

(char*) und als zweiten Parameter einen Pointer auf eine SOCKADDR_IN Strucktur, welche von der Funktion abgefüllt wird

(allerdings nur das sin_addr Feld). Als Rückgabewert liefert sie SOCKET_ERROR bei einem Fehler.
Der erste Parameter kann dabei entweder eine IP als String sein, also zb "192.168.0.1" oder ein Hostname, zB

"www.c-worker.ch". Zuerst wird unsere Funktion inet_addr() verwenden, wenn inet_addr() gelingt, war im übergebenen String

eine IP, falls nicht rufen wir gethostbyname() auf, ging auch das nicht liefern wir SOCKET_ERROR zurück.
Hier nun die Funktion:

Code:


long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr)

{

  long rc;

  unsigned long ip;

  HOSTENT* he;

  /* Parameter prüfen */

  if(hostnameOrIp==NULL || addr==NULL)

    return SOCKET_ERROR;

  /* eine IP in hostnameOrIp ? */

  ip=inet_addr(hostnameOrIp);

  /* bei einem fehler liefert inet_addr den Rückgabewert INADDR_NONE */

  if(ip!=INADDR_NONE)

  {

    addr->sin_addr.s_addr=ip;

    return 0;

  }

  else

  {

    /* Hostname in hostnameOrIp auflösen */

    he=gethostbyname(hostnameOrIp);

    if(he==NULL)

    {

      return SOCKET_ERROR;

    }

    else

    {

      /*die 4 Bytes der IP von he nach addr kopieren */

      memcpy(&(addr->sin_addr),he->h_addr_list[0],4);

    }

    return 0;

  }

}



Das was es eigentlich schon. Nun müssen wir die Funktion noch in unser Beispiel sock.c einbauen. Unter anderem muss main()

nun angepasst werden damit auch die übergebenen Parameter verwendet werden können, und die Anzahl der Parameter muss geprüft

werden. Die Änderungen sind wieder fett hervorgehoben, einige Zeilen müssen auch entfernt werden, diese werden hier einfach

fett auskommentiert.

Code:


//Prototypen

int startWinsock(void);

long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr);

int main(int argc, char** argv)

{

  long rc;

  SOCKET s;

  SOCKADDR_IN addr;

  char buf[256];

  if(argc<2)

  {

    printf("Usage: sock <hostname oder ip des servers>\n");

    return 1;

  }



  .....



  // Verbinden

  memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten

  addr.sin_family=AF_INET;

  addr.sin_port=htons(12345); // wir verwenden mal port 12345

  //addr.sin_addr.s_addr=inet_addr("127.0.0.1");

  rc=getAddrFromString(argv[1],&addr);

  if(rc==SOCKET_ERROR)

  {

    printf("IP für %s konnte nicht aufgeloest werden\n", argv[1]);

    return 1;

  }

  else

  {

    printf("IP aufgeloest!\n");

  }



  .....



Um es zu testen muss natürlich wieder zuerst in einer anderen Konsole socksrv gestartet werden.

Dann kann sock2 zB folgendermassen aufgerufen werden:

sock2 localhost

Und localhost sollte erfolgreich in eine IP aufgelöst werden, und die Verbindung zustande kommen. Falls man ein eigenes

Netzwerk hat kann man das nun auch richtig übers Netz testen. Man startet socksrv auf einem Rechner (zB mit dem namen

machine1) und sock2 auf einem anderen Rechner, als ersten Parameter gibt man sock2 machine1 an, und das ganze sollte

eigentlich einwandfrei laufen, vorausgesetzt es ist ein DNS verfügbar der machine1 in eine IP umwandeln kann oder man hat

lokal in den entsprechenden Dateien einen Eintrag.

Das war es auch schon wieder.

Gibt es noch irgendwelche Fragen, oder wollen Sie über den Artikel diskutieren?

Sprachenübersicht/Programmierung/C / C++/ C#/Netzwerk/Winsock Tutorial Teil 2: Hostnamen auflösen