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
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.
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.
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