Professional Documents
Culture Documents
w w w . Wu T. d e
Fit in 1 Tag
frTCP/IP-Sockets
die Socket-Schnittstelle
WinSock
Beispielcode zur Einbindung von ComServern
TCP/IP-Grundlagen
W&T
w w w . Wu T. d e
Einfhrung
Ver mutlic h sind Sie Prog rammier er oder Programmierer in. Ver mutlic h haben Sie sc hon
frher Per ipherieg erte etwa ber den COM-Port in Ihre Anwendungen eingebunden.
Und nun haben Sie Lust bekommen, diese Gerte direkt ber das Netzwerk einzubinden.
Nachdem Sie die erste Scheu vor der neuen Materie berwunden haben, werden Sie
merken, da der Weg ber das Netzwer k fr Programmierer g ar nicht k omplizierter ist als
der gute alte COM-Port.
Zwar kommen ein paar neue Begriffe hinzu, dafr fllt aber auch manche Ungereimtheit
der COM-Anbindung weg. Also fangen wir doc h gleich an!
Fit fr TCP/IP-Sockets in 1 Tag so knnen Sie vorgehen:
1 . Lesen Sie zuerst Teil 1 Die Socket-Sc hnittstelle So verschaffen Sie sic h nicht allein
schnelle bersicht , sondern finden auch bereits manche wichtige Detailinformation, die
Ihnen spter ein zielgerichtetes Arbeiten ermglicht.
2 . Nun brauchen sie eigentlich schon eine Spielwiese, auf der Sie Ihr neu erworbenes
Wissen erproben knnen. Um nicht gleich mit zwei Anwendungen beginnen mssen,
empf ehlen wir Ihnen, zu diesem Zwec k bei uns einen Com-Server als Testgert zu
bestellen, der dann die Aufgaben des Netzwer k-Kommunikationspar tners (SocketClient oder -Server) bernimmt.
(Falls Sie besonders eilig sind, knnen Sie natrlich auch versuchen, eine Kommunikation zwisc hen zwei Rechnern aufzubauen. Dieser Weg ist anspruchsvoller, da Sie
zwei Prog ramme gleic hzeitig zum Laufen br ingen mssen. Ohne einsc hlgig e Vorerfahrung sollten Sie also lie ber von dieser Idee Abstand nehmen.)
3 . Nun whlen Sie aus Teil 2 Programmierbeispiele Socket-API die Beispiele fr Ihre
jeweilige Programmierumgebung aus. Die Quellen einschlielich aller notwendigen
Includes und Resource-Dateien sowie weitere Beispiele fr Windows 9x /NT knnen Sie
auc h unter http://www.WuT.de herunterladen.
4 . Sptestens beim Durcharbeiten der Programmbeispiele werden Sie auf neue Begriffe
aus der Netzw erkwelt stoen. Doch was Sie zum Verstndnis dieser Begriffe brauc hen,
ist sehr kompakt in Teil 3 TCP/IP-Grundlagen zusammengestellt.
Im Zusammenspiel mit den Programmbeispielen und Ihren eigenen Experimenten sollte
sich Ihnen das erforderliche Ver stndnis bald erschlieen.
Wer trotzdem noch eine ausfhr lichere Einfhrung wnscht, sei auf die Literaturangaben
im Anhang verwiesen.
W&T
w w w . Wu T. d e
Inhalt
Teil 1
Die Socket-Schnittstelle
1.
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
Teil 2
Programmbeispiele
2.
2.1
2.1.1
2.1.2
2.1.3
2.2
2.3
2.4
Teil 3
TCP/IP-Grundlagen
3.1
3.1.1
3.1.2
3.1.3
3.2
3.3
3.4
3.5
3.5.1
3.5.2
3.5.3
Literaturverzeichnis ................................................................................................................. 45
W&T
w w w . Wu T. d e
Teil 1
Die Socket-Schnittstelle
Client-Server-Prinzip
die Socket-Variable
Socket-Funktionen
Host- und Network-Order
WinSock-spezifische Funktionen
Streams und Datagramme
Client- und Server-Applikationen
W&T
w w w . Wu T. d e
1.
Die Socket-Schnittstelle
Das Soc ket-Interface, das unlngst als Neuer ung Einzug in die PC-Welt hielt, wur de vor
mehr als 15 Jahren als Berkley Socket Interface unter BSD-UNIX 4.3 entwickelt. Diese
Schnittstelle ermglicht mittels weniger einfach zu handhabender Befehle den Zugriff auf
die Funktionalitt von TCP/IP; im Laufe der Jahre wurde sie von vielen anderen UNIXSystemen aufgegriffen.
Auch unter Windows 9x gehr t die WinSock.DLL und damit die Funktionalitt der SocketSchnittstelle mittlerweile zum Lieferumfang. Die Entscheidung fr diese Schnittstelle ist
leicht nachzuvollziehen. Sie ermglicht neben der Neuentwicklung von Internetanwendungen auc h das Portieren der Anwendungen von UNIX auf den PC, da sie grtenteils kompatibel zum Berkley Socket ist.
1.1
Client-Server-Prinzip
Internetanwendungen werden nach dem Client-Server-Prinzip erstellt. Der Client ist hier
in den meisten Fllen das Benutzer-Interface und nimmt vom Server bestimmte Dienste in
Anspruch. Er baut in Abhngigkeit vorher def inierter Ereignisse (z.B . dem Starten einer
Internetanwendung durch einen Anwender) die Verbindung zum Server auf und ist somit
der aktive Teil.
Der Server stellt nun den gewnschten Dienst zur Verfgung. Er mu sich stndig in einem
Zustand befinden, in dem er Verbindungsaufforderungen v on Clients entgegennehmen
kann er ist der passive Teil. Ein Server darf niemals einen Dienst vom Client anfordern.
Client und Server mssen die gleiche Sprache sprechen: Sie mssen sich also an einem
gemeinsamen Protokoll orientieren.
Das unterschiedliche Verhalten von Client und Server lt allerdings eine Asymetrie entstehen, die sich in der Verw endung unterschiedlicher Schnittstellen-Befehle bei der Realisierung einer Client- oder Serverapplikation niederschlgt.
1.2
1.3
Die Socket-Variable
Die Socket-Variab le ist vom Typ Integer. Sie hat nic hts mit der Portn ummer der Applikation zu tun, wie oft angenommen wird, sondern ist lediglich ein Handle fr eine Verbindung. Unter dieser Nummer erhlt man vom Treiber mittels verschiedener Befehle alle
Informationen zu der Verbindung, die zu diesem Handle g ehrt.
W&T
w w w . Wu T. d e
Anwendung
Socket-Handle
WinSock.dll
lokale IP-Adresse
lokaler Port
entfernte IP-Adresse
entfernter Port
Flags
Empfangspuffer
Sendepuffer
1.4
Beschreibung
accept
bind
closesocket
connect
getpeername
getsockname
getsockopt
ioctlsocket
listen
recv
recfrom
send
sendto
select
shutdown
socket
W&T
w w w . Wu T. d e
1.5
Little-Endian
(Host-Order)
Big-Endian
(Net-Order)
Little-Endian
(Host-Order)
Big-Endian
(Net-Order)
n+3
31 ... 24
7 ... 0
n+2
23 ... 16
15 ... 8
n+1
n
15 ... 8
7 ... 0
15 ... 8
23 ... 16
7 ... 0
15 ... 8
7 ... 0
31 ... 24
16 Bit WORD
32-Bit DWORD
Da auf allen Intel-PCs der Speicher nach der Host-Order ausgewertet wird (das niederwertige Byte also vor dem hherwer tigen im Speicher steht), ist es notw endig, alle Werte
mit dem Type LONG oder WORD vor der ber gabe an den Treiber in die Network-Order
zu kon vertier en. Analog mssen alle Werte nac h Erhalt vom Treiber in die Host-Order
konvertiert w erden, bevor mit ihnen g erec hnet werden kann. Vorsicht ist auch bei Vergleichen geboten: Sie liefern in Network- und Host-Order nicht das gleiche Ergebnis!
Das Soc ket-Interface stellt hier eine Reihe v on Konvertierungs-Funktionen zur Verfgung. Wer sic h die Tabelle etwas genauer ansc haut, wird feststellen, da es fr jede Ric htung (Network -> Host-Order und Host -> Network-Order) jeweils eine Funktion gibt.
Eigentlic h ist dies eine Doppelung, denn welche Var iante man nimmt sie wird und mu
das gleiche Ergebnis liefer n. Der einzige Vorteil liegt in der besseren Lesbar keit des Programms. Anhand des benutzten Befehls kann man erk ennen, ob der jeweilige Wer t anschlieend in Host- oder Network-Order vorliegt.
Konvertierungsfunktionen
Beschreibung
htonl
ntohl
htons
ntohs
inet_addr
inet_ntoa
Die Funktionen inet_addr() und inet_ntoa() weichen etwas von den anderen ab. Sie
wandeln eine Internetadresse, die als String im Internet Standard Dotted Format vorliegt,
in einen 32-Bit-Wer t (inet_ad dr()) oder umgekehrt (inet_ntoa()).
7
W&T
w w w . Wu T. d e
1.6
Datenbankfunktionen
Diese Funktionen dienen dazu, Informationen ber Namen, IP-Adressen, Netzwerkadressen
und andere Daten vom Treiber zu beziehen. Ein User wird z.B. im Dialogfeld einer
Applikation den Zielhost nicht als IP-Adresse eingeben, sondern den Namen der Station
eintragen. Niemand knnte sich die vielen IP-Adressen im Internet merken. Da sich Namen viel besser einprgen als Nummern, ist es blich, auch hier mit Namen zu arbeiten.
Datenbankfunktionen sorgen z.B. fr die Konvertierung von Namen in IP-Adressen und
umgekehrt. Sie nehmen dafr die Dienste eines Domain Name Ser ver in Anspruch oder
werten lokale Files aus.
Datenbankfunktionen
1.7
Beschreibung
gethostbyaddr
gethostbyname
gethostname
Blockierende Funktionen
Alle Funktionen der Socket-Schnittstelle sind blockierende Funktionen. Bei Datenbankoder Konvertierungsfunktionen wird man die blockierende Wirkung nicht spren, da
diese Funktionen immer sofort ein Ergebnis liefern. Ruft man aber z.B. die Funktion recv()
auf, um Daten vom Socket zu empfangen, wird sie die Kontrolle erst zurckgeben, wenn
tatschlich Daten zum Empfang vorhanden sind.
Um solche blockierenden Wirkungen zu umgehen, ist es unerllich, vor jeder Lese- oder
Schreibaktion die Funktion select() aufzurufen. Sie gibt fr eine gegebene Menge von
Soc kets Auskunft, ob Da ten versandt oder empfang en werden knnen.
Beachten Sie zu diesem Problem auch die Funktion WSAAsynSelect() , eine Windowsspezifische Version von select().
1.8
Erst nach der Initialisierung mit WSAStartup() knnen andere Funktionen erfolgreich
aufgerufen werden. WSAStartup() er laubt es, die erforder liche Version der DLL zu spezifizieren und Details ber die implementier te DLL in der Struktur WSDATA abzulegen.
Analog m u vor dem Beenden des Prozesses auch die Arbeit mit der WinSock.DLL abgeschlossen werden. Die letzte aufzurufende Funktion ist also grundstzlich WSACleanup().
W&T
w w w . Wu T. d e
WinSock-spezif.
Funktionen
Beschreibung
WSAStartup
WSACleanup
Beenden der Arbeit mit den Sockets durch den aktuellen Proze.
WSAAsyncSelect
WSAGetLastError
Die Verwendung von WSAAsyncSelect() der async hronen Version v on select() bringt
viele Vorteile. Diese Funktion erlaubt eine nichtblockierende Arbeit mit Sockets: Sie initialisiert die Benachrichtigung der Applikation ber Windows-Messag es, sobald Netzwerkereignisse fr diesen Socket eintreten.
Die Funktion WSAGetLastError() liefert den letzten Fehlercode eines Socketaufrufs. Gibt
ein Soc ket-Aufruf den Wer t SOCKET_ERROR zurc k, sollte diese Funktion unbedingt
sofort aufgerufen werden.
1.9
Die Strukturen sockaddr und sockaddr_in ha ben den gleichen Inhalt: die Adressfamilie
und die Adresse selbst. In das Array sa_dat[14] der Struktur sockaddr knnen Adressen
aller Familien eing etragen wer den. Die Adressfamilie ist im Inter net immer AF_INET. Die
Struktur sockaddr_in konkretisiert dieses Ar ray auf das Format der Adressierung im Internet:
auf die Portnummer und die IP-Adresse. Dafr bentigt man nur 6 Bytes deshalb auch
die 8 ungenutzten Bytes von sin_zero[8] am Ende der Struktur.
/* WINSOCK.H */
struct in_addr
{ union
{ struct { u_char s_b1, s_b2, s_b3, s_b4; }
S_un_b;
struct { u_short s_w1, s_w2; } S_un_w;
u_long S_addr;
} S_un;
}
Die Struktur in_addr beinhaltet nichts weiter als die IP-Adresse selbst. Sie ermglicht lediglich den Zugriff auf einzelne Bestandteile der IP-Adresse, ohne dabei komplizierte Casts
9
W&T
w w w . Wu T. d e
bilden zu mssen. Je nach Klasse des IP-Netzwerkes kann man mittels dieser Struktur auf
Network- und Host-ID getrennt zugreifen.
/* WINSOCK.H */
struct hostent
{ char FAR *h_name;
char FAR* FAR* h_aliases;
short h_addrtype;
short h_length;
char FAR* FAR* h_addr_list;
Die Struktur hostent ist wichtig fr Datenbankfunktionen. In dieser Struktur findet man
alle Zusatzinformationen zu einer bergebenen Information z.B. Namen und weitere
Alternativnamen zu einer gegebenen IP-Adresse oder alle IP-Adressen zu einem Namen.
Im Normalfall gibt es n ur eine Adresse zu einem Namen, lediglich bei Multi-Homed-Hosts
kann man mehrere IP-Adressen zurckbekommen.
10
W&T
w w w . Wu T. d e
Server
socket()
bind()
listen()
accept()
send()
recv()
recv()
send()
closesocket()
closesocket()
SOCKET iClient;
iClient = socket(AF_INET, SOCK_STREAM, 0);
if(iClient == INVALID_SOCKET)
{
// Fehler
int errcode = WSAGetLastError();
}
Server
socket( )
bind( )
socket( )
bind( )
sendto( )
recvfrom( )
recvfrom( )
closesocket( )
sendto( )
closesocket( )
SOCKET iClient;
iClient = socket(AF_INET, SOCK_DGRAM, 0);
if(iClient == INVALID_SOCKET)
{ // Fehler
int errcode = WSAGetLastError();
}
11
W&T
w w w . Wu T. d e
Teil 2
Programmbeispiele
Socket-API
DOS-Applikationen in C
Windows-95-Applikationen in C
Visual Basic
Java
W&T
w w w . Wu T. d e
Diese kleine Programmier-Ref erenz widmet sich speziell dem Protokoll TCP/IP. Sie finden
hier eine kleine Au swahl an Beispiel-Pr og rammen fr versc hiedene Umgeb ungen
(Windows95/ C, DOS/C, JAVA und VISUAL-Basic), die beim Er stellen einer eigenen
Applikation den Start erleichtern sollen. Sie werden sehen: die Socket-Schnittstelle ist
wirklich leicht zu handhaben. Um einen ersten Erfolg zu erzielen um also Daten zum
Com-Server zu senden oder von dort zu empfangen bedarf es nur weniger Funktionsaufrufe.
Alle Beispiele finden Sie im Internet unter http://www.WuT.de als Download.
13
W&T
w w w . Wu T. d e
2.1
Anwendungsumfeld C: DOS
Beschreibung der Programmierumgebung
Die Beispiele dieses Anleitungsteils sollen kna pp darstellen, wie man Anwendung en fr
den Com-Server mit Hilfe der Socket-Schnittstelle fr das Betriebssystem DOS erzeugt.
Die Programme sind unter DOS oder in der DOS-Box von Windows ausfhrbar und
wurden fr den TCP/IP-Stack v on Novell (LAN Work Place V4.1) erstellt.
Programmierumgebung des Beispiels:
Programmiersprache:
Compiler:
Linker:
Socket API:
C
Microsoft C/C++ Compiler Version 8.0
Microsoft Segmented Executa ble Linker Ver sion 5.50
Novells LAN WorkPlace Windows Sockets
Application Rrogramming Interface (API)
//Socket-Deskriptor
//Adresse des Com-Servers
//Com-Server-Port A vordefinieren
14
W&T
w w w . Wu T. d e
u_long remote_ip;
if(!loaded())
//TCP/IP-Stack installiert?
{ printf("Kein TCP/IP Protokollstack aktiv\n");
exit (1);
}
if(argc < 2)
//Hostname aus Argument bernehmen
{ printf("Kein Hostname angegeben\n");
exit (1);
}
if(argc > 2)
//evtl. Portnummer als 2. Parameter
portnr = atoi(argv[2]);
bzero((char *)&box,sizeof(box)); //Adrestruktur lschen
hostname = argv[1];
//rhost() erwartet (char**)-Argument!
if((remote_ip = rhost(&hostname)) == -1)
{ printf("Unbekannter Hostname\" %s\"\n", argv[1]);
exit(1);
}
//ffne Handle fr TCP-Transport
if((sd = socket(PF_INET,SOCK_STREAM, 0)) < 0)
{ soperror("socket");
exit(1);
}
box.sin_family = AF_INET;
box.sin_port = htons(portnr);
//Ziel Port-Nummer
box.sin_addr.s_addr = rhost(&hostname); //Ziel IP-Adresse
//ffne Verbindung zum COM-Server Port A
if(connect (sd, (struct sockaddr*)&box,
sizeof(box)) < 0)
{ soclose(sd);
//schliee Handle wieder
soperror("connect");
exit(1);
}
//empfange u. sende Daten,bis ALT Q gedrckt wird
printf("Verbunden mit COM-Server %s:%d\n", inet_ntoa(box.sin_addr),
htons(box.sin_port));
terminal();
soclose(sd);
}
void terminal(void)
{
fd_set rd_ready,wr_ready;
struct timeval maxwait;
int s_len = 0;
int r_len = 0;
int z_count = 0;
char key;
for(;;)
15
W&T
w w w . Wu T. d e
{
FD_ZERO(&rd_ready);
FD_SET (sd,&rd_ready);
FD_ZERO(&wr_ready);
FD_SET (sd,&wr_ready);
maxwait.tv_sec = 0;
maxwait.tv_usec = 10;
if(select(sd+1,&rd_ready,&wr_ready,
(fd_set*)0,&maxwait) == 0) continue;
if(FD_ISSET(sd, &rd_ready)) //liegen Daten vor?
{ if((r_len=soread(sd, RecBuf, BUF_SIZE))>0)
{ *(RecBuf[r_len]) = 0 //markiere Stringende
printf("%s",RecBuf); //gebe Daten auf Bildschirm aus
}
else if(r_len == 0)
//regulrer Verbindungsabbau
{ printf("\nCOM-Server hat die Verbindung beendet\n");
return;
}
else if(r_len <= 0)
//Verbindungsfehler
{ soperror("soread");
return;
}
}
if(kbhit())
//Tastatureingaben lesen
{ key = getch();
if(!key)
// Sonderzeichen
{ if(getch()==16)
// ALT Q -> beende Terminal
{ printf("\n");
return;
}
}
else
{ SendBuf[z_count++] = key;
if(key==0x0D)
//ENTER->sende Zeile an Com-Server
{ SendBuf[z_count++] = 0x0A;
s_len = z_count;
z_count = 0;
}
}
}
//sobald eine Eingabezeile komplett ist (und das API bereit ist),
//Zeile absenden:
if(s_len > 0 && FD_ISSET(sd, &wr_ready))
{ if(sowrite(sd, SendBuf, s_len) < 0)
{ soperror("sowrite()");
return;
}
s_len = 0;
}
}
}
16
W&T
w w w . Wu T. d e
2.1.2
//Server Port
char SendBuf[BUF_SIZE];
char RecBuf [BUF_SIZE];
void terminal(int sd);
void main (void)
{
int sd,ss;
//Socket-Deskriptoren
struct sockaddr_in box,loc;
//Adressen von Com-Server und PC
int box_size = sizeof(box);
fd_set rd_ready;
//Flags
struct timeval maxwait;
//max. Wartezeit fr select()
bzero((char *)&loc, sizeof(loc));
//Adrestrukturen lschen
bzero((char *)&box, sizeof(box));
if(!loaded())
//TCP/IP-Stack installiert?
{ printf("Kein TCP/IP Protokoll-Stack aktiv\n");
exit (1);
}
// ffne Handle fr TCP-Transport
if((ss = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{ soperror("socket()");
exit(1);
}
loc.sin_family = AF_INET;
loc.sin_port = htons(SERV_SOCKET);
loc.sin_addr.s_addr = getmyipaddr(); //"0" wre auch zulssig
17
W&T
w w w . Wu T. d e
18
W&T
w w w . Wu T. d e
2.1.3
Programmbeispiel: UDP-Server
Das Programm udpserv.c realisiert einen UDP-Server auf dem Soc ket 2000. Der ComServer wird im UDP Mode konfiguriert und sendet alle seriellen Daten an diesen UDPSer ver.
UDP bietet keinerlei Verbindungskontrolle. Mit UDP sollte man demnac h n ur arbeiten,
wenn die Daten zwischen dem seriellen Endgert und Ihrer Endanwendung bereits mit
einem Protokoll bertragen werden, das seinerseits einen fehlerfreien Datentransfer gewhrleistet.
Das Programm udpserv.c gibt alle empfangenen Daten auf dem Bildschirm aus und sendet
smtliche Tasta tureingaben nach dem Drc ken der Entertaste an den Com-Serv er-P ort,
von dem zuletzt Daten empfangen wurden.
/***********************************************
*** udpserv.c
***
*** UDP Server-Programm: Terminal-Funktion ***
*** Beenden des Programms mit ALT Q
***
************************************************/
#include
<stdio.h>
#include
<conio.h>
#include
<nw/socket.h>
#define SERV_SOCKET 2000
//Server-Port
#define BUF_SIZE 512
char SendBuf[BUF_SIZE];
char RecBuf [BUF_SIZE];
void main (void)
{
int sd;
struct sockaddr_in box;
struct sockaddr_in loc;
struct timeval maxwait;
fd_set rd_ready,wr_ready;
int s_len = 0;
int r_len = 0;
int z_count = 0;
int boxlen = sizeof(box);
char key;
//Socket-Deskriptor
//Struktur Com-Server-Port
//Struktur PC
//Wartezeit auf API
//Flags fr select()
19
W&T
w w w . Wu T. d e
20
W&T
w w w . Wu T. d e
//Wurden Zeichen von der Tastatur gelesen und ist das API zum Senden bereit?
if(s_len > 0 && FD_ISSET(sd, &wr_ready))
{ if(sendto(sd, SendBuf, s_len, 0,
(struct sockaddr*)&box, sizeof(box)) < 0)
{ soperror("sendto()");
goto quit;
}
s_len = 0;
//setze Zeichenanzahl auf Null
}
}
//Ende for(;;)
quit:
soclose(sd);
exit(1);
}
21
W&T
w w w . Wu T. d e
2.2
/************************************************ ****************
*
*
*
clnt_tcp.c
(Win32 Application)
*
*
Microsoft Visual C++ 5.0
*
*
*
************************************************* ****************
* TCP-Client: Der Client ffnet die Verbindung zum TCP-Server, *
* dessen Adresse oder Name in der Dialogbox eingetragen wird.
*
* Alle im Feld Senden eingegebenen Daten werden zum Server
*
* bertragen, alle empfangenen Daten im Fenster Empfang
*
* ausgegeben. Im Statusfenster werden die gerade ausgefhrten
*
* WINSOCK-Funktionen angezeigt.
*
****************************************************************/
#include <winsock.h>
#include <stdio.h>
#include "resource.h"
#define WM_SOCKET (WM_USER + 1)
#define SERVER_PORT 8000
22
W&T
w w w . Wu T. d e
23
W&T
w w w . Wu T. d e
case WM_COMMAND:
switch(LOWORD(wP))
{ case IDCANCEL:
EndDialog(hWnd, 0);
break;
//Schaltflchen-Nachrichten
//CloseBox des Fensters
case IDC_SEND:
//Daten senden
if(iClient != INVALID_SOCKET)
{
char Buffer[255];
int iSendLen;
ShowStatus(hWnd, "FD_WRITE"); //Serveradresse einlesen
iSendLen = GetWindowText(GetDlgItem (hWnd,IDC_SENDDATA),
Buffer, sizeof(Buffer));
ShowStatus(hWnd, "send()...");
if(send(iClient, Buffer, iSendLen,0) != SOCKET_ERROR)
{ ShowStatus(hWnd, "... fertig");
EnableWindow(GetDlgItem(hWnd, IDC_SEND), TRUE);
}
else
{ if(WSAGetLastError() == WSAEWOULDBLOCK)
ShowStatus(hWnd, "... blockiert");
else
ShowStatus(hWnd, "Fehler bei send()");
ShowStatus(hWnd, "closesocket()");
EnableWindow(GetDlgItem(hWnd, IDC_SEND), TRUE);
closesocket(iClient);
iClient = INVALID_SOCKET;
ShowStatus(hWnd, "Abbruch");
}
}
break;
case IDC_CONNECT:
{ SOCKADDR_IN sin;
char remoteIP[64];
char Buffer[80];
//Zieladresse auslesen
GetWindowText(GetDlgItem(hWnd, IDC_DESTADDRESS),
remoteIP, sizeof(remoteIP));
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERVER_PORT);
//IP-Adresse -> Dot-Notation
ShowStatus(hWnd, "inet_addr()");
sin.sin_addr.s_addr = inet_addr(remoteIP);
//Adresse ber DNS auflsen
if(sin.sin_addr.s_addr == INADDR_NONE)
{ HOSTENT *he;
ShowStatus(hWnd, "gethostbyname()");
he = gethostbyname(remoteIP);
if(he)
sin.sin_addr.s_addr = *((DWORD*)he->h_addr);
24
W&T
w w w . Wu T. d e
else
{ ShowStatus(hWnd, "unglitige Internet-Adresse");
break;
}
}
//Zieladresse protokollieren
wsprintf(Buffer, "Adresse: 0x%08lx", ntohl(sin.sin_addr.s_addr));
ShowStatus(hWnd, Buffer);
//Socket erzeugen
ShowStatus(hWnd, "socket()");
iClient = socket(AF_INET, SOCK_STREAM, 0);
if(iClient == INVALID_SOCKET)
{ ShowStatus(hWnd, "Fehler beim Allokieren des Connect-Sockets");
ShowStatus(hWnd, "Kein Verbindungsaufbau mglich");
break;
}
//asynchronen Mode aktivieren
ShowStatus(hWnd, "WSAAsyncSelect()");
if(WSAAsyncSelect(iClient,
hWnd,
WM_SOCKET,
FD_CONNECT |
FD_READ |
FD_CLOSE) == 0)
{ ShowStatus(hWnd, "connect()");
if(connect(iClient,(SOCKADDR*)&sin,sizeof(sin)) == SOCKET_ERROR)
{ if(WSAGetLastError() == WSAEWOULDBLOCK)
{ ShowStatus(hWnd, "Warte...");
//Senden-Schalflche deaktivieren
EnableWindow(GetDlgItem(hWnd, IDC_SEND),FALSE);
break;
}
}
}
else
ShowStatus(hWnd, "Fehler bei WSAAsyncSelect()");
ShowStatus(hWnd,"closesocket()");
closesocket(iClient);
iClient = INVALID_SOCKET;
}
break;
case IDC_CLOSE:
ShowStatus(hWnd,"closesocket()");
closesocket(iClient);
iClient = INVALID_SOCKET;
EnableWindow(GetDlgItem(hWnd, IDC_CLOSE), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_CONNECT), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_SEND), FALSE);
break;
}
break;
25
W&T
w w w . Wu T. d e
case WM_DESTROY:
if(iClient != INVALID_SOCKET)
closesocket(iClient);
break;
}
return FALSE;
//Fenster schlieen
//Socket schlieen
}
/*************************************************
* WinMain: Haupteinsprungspunkt
*
**************************************************
* Parameter: Standarddialogparameter
*
* Rckgabewert: 0
*
*************************************************/
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
WSADATA wsadata;
//Version 1.1 der Winsock-DLL
if(WSAStartup(MAKEWORD(1,1), &wsadata) == 0)
{
DialogBox(hInstance,
//Dialog anzeigen
MAKEINTRESOURCE(IDD_WSCLIENT),
NULL,
WSClientProc);
WSACleanup();
//Winsock-DLL aufrumen
}
else MessageBox(0,
"Fehler beim Initialisieren der WINSOCK.DLL",
"WSClient.EXE", 0);
return 0;
}
26
W&T
w w w . Wu T. d e
2.3
Anwendungsumfeld Visual-Basic
Beschreibung der Programmierumgebung
Dieses Beispiel zeigt, wie man eine TCP-Client-Anwendung fr den Com-Server mit Hilfe
der Socket-Sc hnittstelle in Visual Basic erstellt. Es wird das Winsock-Steuer element von
Microsoft verwendet, da a b der Visual Basic Ver sion 5 zum Standardliefer umfang gehrt.
Systemvoraussetzungen:
Microsoft Windows 95, 98 oder NT 4.0
Visual Basic
Compiler:
TCP/IP-Control:
27
W&T
w w w . Wu T. d e
das Ereignis Send-Complete so wie der Fehlerbehandlung mssen eigene Progr amme
ggf. erweitert werden.
28
W&T
w w w . Wu T. d e
29
W&T
w w w . Wu T. d e
2.4
Anwendungsumfeld Java
Beschreibung der Programmierumgebung
Dieses Beispiel zeigt, wie eine einfache Java-Anwendung fr den Com-Server aufgebaut
ist. Das Programm ist unter Windows in der DOS-Box mit Hilfe eines Java-Interpreters
ausfhrbar. Voraussetzung ist, da der Microsoft Windows TCP/IP- Stack installiert ist.
Programmierumgebung des Beispiels:
System:
Windows 9x
TCP/IP-Stack:
Programmiersprache:
Java 1.3
Compiler:
/******************************************************************/
/* ComportTcp.java
Win32 Application
*/
/*
Borland JBuilder 4.0
*/
/******************************************************************/
/* Beispielprogramm fr einen Client
*/
/* Die IP-Adresse des Servers mu beim Start des Programms als
*/
/* Parameter bergeben werden.
*/
/* - Eingaben mssen mit <RETURN> beendet werden.
*/
/* - Empfangene Daten werden byte-weise ausgegeben.
*/
/* - Der Empfang wird von einem eigenen Thread bearbeitet.
*/
/* - Das Programm wird mit x+<ENTER> beendet.
*/
/******************************************************************/
//Java Library Packages
import java.io.*;
//classes for file I/O
import java.net.*;
//classes to perform low-level Internet I/O
class ComportTcp
{ public static void main( String[] args )
{ try
{ if( args.length < 1 )
{ System.out.println( "Call: ComportTcp <IP-Address>" );
return;
}
String strAddress = args[0];
// COM-Server IP-Address
int iPort = 8000;
// COM-Server Port A (TCP)
System.out.println( "Server IP-Address: " + strAddress );
Socket
socket = new Socket( strAddress, iPort );
DataInputStream incoming = new DataInputStream( socket.getInputStream() );
DataOutputStream outgoing = new DataOutputStream( socket.getOutputStream() );
System.out.println( "" );
System.out.println( "Start receive thread!
End Session: x+<ENTER>" );
System.out.println( "-------------------------------------------------" );
30
W&T
w w w . Wu T. d e
}
catch( IOException e )
{ System.out.println( "Error" + e );
}
}
}
class ThreadedReadStreamHandler extends Thread
{ DataInputStream incoming;
boolean more = true;
ThreadedReadStreamHandler( DataInputStream i )
{ incoming = i;
}
public void run()
{ try
{ byte[] b = new byte[1];
while( more )
{ b[0] = incoming.readByte();
System.out.write( b, 0, 1 );
}
incoming.close();
}
catch( Exception e )
{
}
}
31
W&T
w w w . Wu T. d e
Teil 3
TCP/IP-Grundlagen
Das Internet-Protokoll
Die IP-Adresse
Netzwerkklassen
Routing
Subnets
Die Protokolle UDP und TCP
W&T
w w w . Wu T. d e
3.1
IP Internet Protocol
Das Internet-Protokoll definiert die Grundlage der Datenkommunikation auf der untersten
Ebene. Es ermglicht unabhngig von den verwendeten physikalischen Medien das Zusammenfgen vieler unterschiedlicher Netzwerk- und Hardwarearchitekturen zu einem
einheitlichen Netz.
Das Internet-Protokoll gewhrleistet die bertragung der Daten durch einen verbindungslosen, nicht abgesicherten Transport. Fr Sicherheitsmechanismen sind bergeordnet Protokolle wie TCP verantwortlich.
Grundlagen fr netzberg reifende Ver stndigung:
3.1.1
FTP
TELNET
Web
TFTP
SOCKET-SCHNITTSTELLE
Transport Layer
TCP
UDP
Network Layer
ICMP
ARP
IP
Hardwaresteuerung
RARP
Physical Layer
bertragungsmedium: Ethernet, SLIP, PPP, u.s.w.
3.1.2
Internetadressen
Jeder Host im Internet hat eine weltweit einmalige Adr esse. Diese IP-Adresse ist ein 32-BitWer t, der b licherweise zur besseren Lesbarkeit in Dot-Notation also byteweise dur ch
Punkte getrennt angegeben wird.
33
W&T
w w w . Wu T. d e
172.16.231.8
Dot-Notation:
32bit Address:
decimal:
2 886 788 872
hexadecimal:
0xAC10E708
Host-ID: 59144
Die IP-Adresse ist in die Netzwerk- und die Host-ID unterteilt. Wieviel Bits jeweils fr
Netzwerk- und Host-ID verwendet werden, hngt von der Klasse des IP- Netzwerks ab.
Diese Netzwerkklasse kann wie in der unter en Tabelle gezeigt an den hchsten Bits der
Adresse abgelesen werden:
31
24
Class A
Class B
1 0
Class C
1 1 0
Class D
1 1 1 0
Class E
1 1 1 1 0
16
Net-ID
Host-ID
Host-ID
Net-ID
Host-ID
multicast address
reserved for future use
Aus der Definition der Netzwer kklassen ergeben sic h damit die folgenden Adrerume:
Class
Lowest Net-ID
Highest Net-ID
0.1.0.0
126.0.0.0
128.0.0.0
191.255.0.0
192.0.1.0
223.255.255.0
224.0.0.0
239.255.255.255
240.0.0.0
247.255.255.255
blic herweise w erden jedoch nur IP-Adressen der Klassen A bis C ver geben. Mit den
Klassen D und E kommt man nicht in Berhrung: Die Klasse D umfat Netze fr
Multicasting und die Klasse E ist fr Forschungszwecke reserviert.
34
W&T
w w w . Wu T. d e
Die folgenden Internetadressen haben eine besondere Bedeutung und drfen nicht als
Adresse an einen Internet-Host vergeben werden:
meint aktuellen Host mit
Netzwerk- und Host-ID
meint Host mit dieser Host-ID
im aktuellen Netz
Broadcast im lokalen Netz
alle Bits 0
alle Bits 0
Host-ID
alle Bits 1
3.1.3
Net-ID
alle Bits 1
01111111
alle Bits 1
Format IP-Datagram-Header:
0
VERS
HLEN
16
31
TOTAL LENGTH
IDENTIFICATION
TIME TO LIVE
19
SERVICE TYPE
FLAGS
PROTOCOL
FRAGMENT OFFSET
HEADER CHECKSUM
SOURCE IP ADDRESS
DESTINATION IP ADDRESS
IP OPTIONS (IF ANY)
PADDING
DATA AREA
......
version:
hlen:
service type:
total length:
identification:
flags (3bit) :
W&T
w w w . Wu T. d e
time to live:
protocol:
header checksum:
source IP address:
destina tion IP addr.:
IP options (variab.):
padding:
Zhler, der bei jedem Router dekrementier t wird. Wird der Wert 0
erreicht, wird das Paket verworfen.
Nr. des bergeordneten Protokolls (z.B. TCP=6, UDP=17, ...)
Checksumme ber den Header
IP-Adresse des Absenders
IP-Adresse des Empfngers
IP-Optionen, sofern bentigt
Fllb ytes, um die Headerlnge auf ein Vielfaches von DWORDs
zu bringen
36
W&T
w w w . Wu T. d e
3.2
ETHERNET 128.10.0.0
128.10.2.3
IDEFIX
multi-homed
host
128.10.2.8
128.10.2.26
TROUBADIX
MIRACULIX
Ethernet host
Ethernet host
192.5.48.3
OBELIX
ASTERIX
ROUTER
128.10.2.70
192.5.48.7
TOKEN
RING
192.5.48.0
ROUTER
192.5.48.6
To ARPANET
10.0.0.37
192.5.48.1
MAJESTIX
token ring host
Die obenstehende Abbildung z eigt das Beispiel eines Netzwer ks mit Hosts und Routern.
Der Host IDEFIX ist ein multi-homed Host: Er hat Zugang zu mehreren Netzwerken
(z.B. ber zwei Ethernetkarten), verfgt aber ber keine Routersoftware.
Die Hosts IDEFIX, TROUBADIX und MIRACULIX gehren einem Class-B- Netz
(128.10.0.0) an. Das Token-Ring-Netz ist ein Class-C-Netz (192.5.48.0), welches durch
den Router OBELIX mit dem Arpanet (Class-A-Netz 10.0.0.0) verbunden ist.
37
W&T
w w w . Wu T. d e
3.3
Subnets
Wenn ein lokales Netz nicht ausr eicht oder w egen seiner Gre (z.B. bei Class-A-Netz en
mit ber 16 Millionen Hosts) zu unhandlic h ist, wird es in weitere Teilnetzwer ke sogenannte Subnets untergliedert. Unterschiedliche Netztechnologien in den einz elnen Abteilungen, Beschrnkung en hinsichtlich der Ka bellnge und der Anzahl der angesc hlossenen Stationen sowie Performance-Optimierung sind weitere Grnde, Netzwerke in kleine
Segmente aufzuteilen.
Da die Struktur der IP-Adresse keine Mglichkeit mehr bot, diese zustzliche Kodierung
in der Adresse selbst unterzubringen, wurde die Subnet-Mask eingefhrt. Sie definiert,
welche Bits der Host-ID dazu verwendet werden, die Subnet-ID zu kodieren und welche
die ID des Hosts bezeichnen.
Die Subnet Mask wird vom Administrator festgelegt und wie die IP-Adr esse in DotNotation (z.B. 255.255.255.128) dargestellt.
Wer den Subnets gebildet, m u der beschr iebene Routing-Algorithm us erweitert w erden,
da die Net-ID des Empfngers mit der des aktuellen Hosts identisch sein kann, obwohl sich
beide in unterschiedlichen lokalen Netzen befinden. Deshalb mssen zustzlich auch die
Subnet-IDs von Empfnger und aktuellem Host verglichen werden. Sind diese ebenfalls
identisch, kann direkt geroutet werden.
Binroperationen mit der Subnet Mask:
Host-ID = IP-Address AND(NOT(Subnet-Mask))
Net-IDS =
172.16.233.200
10101100
00010000
11101001
11001000
Subnet-Mask:
255.255.255.128
11111111
11111111
11111111
10000000
Host-ID:
72
00000000
00000000
00000000
01001000
Net-ID:
172.16.0.0
10101100
00010000
00000000
00000000
Net-IDS:
172.16.233.128
10101100
00010000
11101001
10000000
Subnet-ID:
0.0.233.128
00000000
00000000
11111111
10000000
38
W&T
w w w . Wu T. d e
3.4
172.16.231.7
0x00C03D000D61
172.16.231.12
0x00C03D002AD9
172.16.231.64
0x00C03D004A05
ARP Request:
Beispiel:
0x00C03D002AD9
172.16.231.12
0xFFFFFFFF
172.16.231.64
0x00C03D002AD9
0.0.0.0
0xFFFFFFFF
255.255.255.255
RESPONSE an Absender:
172.16.231.12
0x00C03D002AD9
172.16.231.64
0x00C03D004A05
auf diesem
Host ist ein
RARP-Daemon
aktiv
ARP / RARP-Response:
Beispiel:
0x00C03D004A05
172.16.231.64
0x00C03D2AD9
172.16.231.12
Die Zuordnung von Ethernet-Adr esse und IP-Adresse wird in einer Tabelle gespeichert
und erst nach einem Timeout gelscht.
Achtung:Bei nderung dieser Zuordnung (z.B. Zuweisen der gleichen IP-Adresse an ein Austausch-
gert) werden Sie u.U. keine Verbindung zum Empfnger erhalten. Steht der Befehl arp
nicht zur Verfgung, schafft hier nur Warten, ein Neustar t des Rechners oder die Vergabe
einer neuen IP-Adresse Abhilfe.
39
W&T
w w w . Wu T. d e
3.5
Transport Layer
3.5.1
FTP-Server Telnet-Client
Port 21
Port 1028
TUNIX
172.16.231.8
IP: 172.16.231.8
Port 1028
TCP/IP Protokollsoftware
IP: 172.16.231.8
Port 80
Internet
IP: 172.16.231.8
Port 1028
IP: 172.16.231.8
3
Port 1028
Fr bekannte Anwendungen werden feste Ports vergeben, auf die sich jede Anwendung beim
Verbindungsaufbau beziehen kann. Der Bereich von 0 bis 1023 enthlt deshalb reservierte
Portnummern. Diese drf en unter keinen Umstnden fr eigene Anwendungen verwendet
werden. Die komplette Liste der normierten Dienste finden Sie im RFC 1700 (1994).
ftp://ftp.isi.edu/in-notes/iana/assignments/port-numbers
// Ports
http://sunsite.auc.dk/RFC
// RFCs
Hier eine kurze Aufstellung von Applikationen und deren Port-Nummern:
Anwendung
Port
Protokoll
Beschreibung
ftp
21
udp / tcp
File-Transfer
telnet
23
udp / tcp
Telnet
smtp
25
udp / tcp
domain
53
udp / tcp
tftp
69
udp / tcp
Trivial File-Transfer
www-http
80
udp / tcp
sftp
115
udp / tcp
snmp
161
udp / tcp
SNMP
...
40
W&T
w w w . Wu T. d e
3.5.2
16
31
UDP CHECKSUM
DATA
...
Source Por t:
Destination Port:
Lnge:
Checksumme:
3.5.3
Port des Absenders; wird fr das Rc ksenden von Da ten durch den
Empfnger bentigt.
Ziel-Port, an den das Datenpaket beim Empfnger bertragen werden soll.
Gre des UDP-Datagramms in Byte (Header und Daten).
Checksumme ber das UDP-Datagramm, jedoch optional (wird sie
nicht genutzt, erscheint in diesem Feld eine 0).
41
W&T
w w w . Wu T. d e
10
16
SOURCE PORT
24
31
DESTINATION PORT
SEQUENCE NUMBER
ACKNOWLEDGMENT NUMBER
HLEN
RESERVED
CODE BITS
WINDOW
CHECKSUM
URGENT POINTER
PADDING
DATA
......
Source Por t:
Destination Port:
Sequence No:
Acknowl. No:
HLEN:
Code Bits:
Window:
Checksum:
Urgent Pointer:
Options:
URG
2:
ACK
3:
PSH
4:
RST
5:
SYN
6:
FIN
Anzahl der Bytes (ausgehend v on dem im Feld Ackno wledgementNo. angezeigten Byte), fr deren Entgegennahme der Empfnger
bereit ist
Checksumme ber das TCP-Datagramm und einen Pseudoheader
wenn das URG-Flag gesetzt ist, gibt dieser Wert den Offset des ersten
Bytes hinter den dr ingenden Da ten am Anfang der Segmentdaten an
Optionen (die wichtigste Option: maximale Segmentgre)
42
W&T
w w w . Wu T. d e
Aufbau:
Der Client sendet ein Paket, in dem in den Code-Bits das Flag SYN gesetzt ist. Der
Server besttigt den Empfang mit dem Fla g ACK und setzt seiner seits das Flag SYN.
Beide synchronisieren sich auf die Sequence-No. der Gegenstation.
Client
Send Flag SYN
seq = x
Receive SYN+ACK
Send Flag ACK
ack = y+1
Server
SYN
SYN+ACK
ACK
In der Option Maximum Segment Size kann jede Seite festlegen, wieviel Byte sie
maximal in einem Segment nach dem TCP-Header empfangen kann.
Abbau:
Das Schlieen einer Verbindung kann vom Client oder vom Ser ver ver anlat werden.
Hierzu wird in den Code-Bits das Flag FIN gesetzt. Erst wenn beide Seiten dieses Flag
gesetzt haben, g ilt die Verbindung als geschlossen.
Receive FIN+ACK
Send ACK ack=y+1
FIN
Receive FIN
ACK
FIN
ACK
43
W&T
w w w . Wu T. d e
Flusteuerung
TCP verfgt ber mehrere Mechanismen, zur sicheren und effizienten bertragung von
Daten. Hier ein paar der wichtigsten Regeln:
Der Sender mu alle Daten solange bereithalten, bis sie vom Empfnger besttigt
wurden.
Bei fehlerhaften Paketen (z.B. Paketen mit fehlerhafter Checksumme) gibt der Empfnger die letzte Acknowledgment-Number zurc k, woraufhin der Sender das P aket
wiederholt.
Gehen P akete verlor en, wiederholt der Sender nac h Ablauf en eines Timeouts alle
Pakete nach dem zuletzt empfangenen Ackno wledgment.
Mit dem F eld Windows teilt der Empfnger in jedem Paket mit, wieviel Empfangsspeicher er noch hat. Enthlt das Feld den Wer t 0, stellt der Sender die ber mittlung
ein, bis er v om Empfnger ein Paket mit dem Wert Windows ungleic h Null erhlt.
Da der Sender stndig ber die aktuelle Buffergre des Empfngers informiert ist,
mu er nicht auf die Besttigung jedes einzelnen Paketes warten, sondern kann so viele
Daten senden, bis der Buffer des Empfngers gefllt ist. Der Empfnger besttigt
dabei immer einen Teil des Empf angs-Bytestroms und nicht die einz elnen Pakete.
Dadur ch knnen Teile von Paketen oder auch mehrer e Pakete auf einmal besttigt
wer den. Diese Methode nennt man Windowing.
44
W&T
w w w . Wu T. d e
Literaturverzeichnis
INERNET intern
Tischer und Jennrich
Ver lag: DATA Becker
ISBN 3-8158-1160-0
45