TCP/IP is een protocol suite die ontwikkelt is door het Amerikaanse Ministerie van
Defensie. Deze suite biedt een aantal protocollen, zeg maar
afspraken, om computersystemen met elkaar te laten communiceren. Deze
systemen kunnen dicht bij elkaar staan en via één kabel
met elkaar verbonden zijn, maar ook is het mogelijk dat deze systemen
duizenden kilometers uit elkaar staan en dat daar diverse systemen
tussen zitten die er wel voor zorgen dat twee systemen met elkaar
kunnen communiceren.
We zien hier twee systemen die met elkaar willen communiceren. Als basis van de
communicatie worden de hardware adressen van de netwerkkaarten
gebruikt. Deze adressen zijn 48 bits lang (6 bytes) waarbij de
hoogste drie bytes gereserveerd zijn om de fabrikant aan te duiden,
en de laagste drie bytes zijn een unieke code die door de fabrikant
toegewezen wordt. Indien een fabrikant door zijn codes heen is, kan
hij een nieuwe “fabrikant-code” aanvragen.
De software in de tweede laag is in staat om aan de hand van het IP adres te bepalen of
een systeem op hetzelfde netwerk aangesloten is of op een extern
netwerk zit. Door het ARP (address resolution protocol) wordt de
vraag “wie heeft adres x.x.x.x op het netwerk gesteld. Indien een systeem dit adres heeft zal
dit antwoorden met: “Dat ben ik, stuur maar naar MAC adres "yy.yy.yy.yy.yy.yy ”.
Daarna kan de communicatie beginnen en worden de pakketten verzonden.
In bovenstaande afbeelding is het op vaststellen van het benodigde MAC adres goed
zichtbaar.
2.2 Communicatie tussen twee systemen op verschillende netwerken.
In de afbeelding op de volgende pagina worden de twee systemen gescheiden door een
router. Dit apparaat is in staat om datapakketjes over te zetten van
het ene netwerk naar het andere, waarbij volgens een bepaald protocol
een route gekozen wordt. De werking van een router valt buiten het
bereik van dit artikel en wordt verder niet behandeld. Voor nu is het
voldoende om te begrijpen dat de router zorgt voor het overzetten van
datapakketjes naar een ander netwerk.
|
A wil bericht sturen naar B, ziet aan adres dat dit niet lokaal is |
A vraagt: "wie is B?" |
R antwoordt: "Dat ben ik. Mijn MAC adres is ......." |
A stuurt pakket naar R, R stuurt pakket door naar B. |
of: A stuurt pakket direct naar R omdat B op ander netwerk zit |
Deze communicatie is vergelijkbaar met de communicatie op hetzelfde netwerk. Het verschil zit er in dat systeem A vraagt wie B is, en dat de router R antwoordt
dat hij B is. A stuurt dan het pakketje naar R, die het weer
doorstuurt naar B. Een andere mogelijkheid is dat A het pakketje
rechtstreeks naar R stuurt omdat A weet dat B op een ander netwerk
zit, en A weet dat R de pakketjes kan bezorgen. De gekozen werking
ligt aan de implementatie van het ARP protocol in de systemen.
3. Adressering
In het algemeen heeft elke manier van communiceren een eigen adressering. Drie bekende
protocollen zijn:
NetBeui van Microsoft en IBM; hierbij wordt gebruik gemaakt van NetBIOS namen. NetBeui is het
protocol, NetBIOS is de api (application program interface, een
manier om systeemfuncties aan te roepen). NetBIOS namen zijn
maximaal 15 karakters lang en kennen geen netwerk informatie.
Derhalve is NetBeui niet routeerbaar, dat houdt in dat systemen op
verschillende netwerken niet met elkaar kunnen communiceren, zonder
daarvoor speciale truukjes voor uit te halen.
IPX/SPX van Novell; hierbij worden adressen gebruikt die wel een netwerkdeel en een
systeemdeel bevatten. Dit maakt IPX/SPX wel routeerbaar. IPX is net
als TCP de connection oriented verbinding, SPX is de connectionless
verbinding.
TCP/IP, de algemeen geaccepteerde standaard in communicatie. Een TCP/IP adres kent net als IPX/SPX een netwerkdeel en een systeemdeel. Het IP-adres (zoals
dit in de volksmond genoemd wordt) zijn vier getallen, gescheiden
door een punt. Het netwerkdeel, ookwel netwerkadres genoemd, wordt
vastgelegd door het subnetmasker. Ook dit zijn vier getallen,
wederom gescheiden door een punt. De bits in het subnetmasker die
gezet (1) zijn, geven aan dat het overeenkomstige bit in het
IP-adres tot het netwerkadres gerekend moet worden.
Bijvoorbeeld:
IP-adres =
10.61.21.5 Subnetmasker=255.255.255.0
Het netwerkadres is
dan:
00001010 00111101 00010101 00000101
11111111 11111111 11111111 00000000
00001010 00111101 00010101 00000000 =
10.61.21.0
In dit voorbeeld zijn de getallen in het
subnetmasker makkelijk gekozen, maar er is niets op tegen om meer of
minder bits voor het netwerkadres te reserveren. Zolang de bits maar
binnen de klasse en aaneengesloten blijven is er niets aan de hand.
Deze klassen zijn als volgt vastgelegd:
Klasse: | Eerste getal: | Voorbeeld: | Subnetmasker: |
Klasse A: | 0 - 126 | 10.61.21.5 | 255.0.0.0 |
Klasse B: | 128 - 191 | 172.16.43.6 | 255.255.0.0.0 |
Klasse C: | 192 - 223 | 192.168.1.40 | 255.255.255.0 |
Klasse D: | 224 - 239 | broadcast | |
Klasse E: | 240 - 254 | experimental | |
Over IP-adresseringen zijn al complete boeken geschreven; voor dit artikel
is bovenstaande sumiere informatie voldoende. Laten we verder gaan
met poorten.....
4. Poorten
Een poort is een 16 bits getal waaraan specifiek proces (service) gekoppeld is en dat het begin en
eindpunt van een connectie aangeeft. Met andere woorden, de poort
geeft aan welke dienst van een systeem gevraagd wordt en welk
programma deze dienst gevraagd heeft.
diensten aangeboden worden. Zo wordt een webserver niet alleen
gebruikt om webpagina's aan te bieden via het http protocol, maar
vaak ook om bestanden te downloaden met het ftp protocol. Om nu
onderscheid te maken welke dienst gevraagd wordt, wordt een
poortnummer meegegeven. Andersom, het systeem dat de dienst vraagt
kan ook zelf diensten aanbieden en moet derhalve meegegeven naar
welke poort de server het antwoord kan sturen.
In onderstaande afbeelding is
in regel 3 te zien dat een dienst gevraagd wordt op poort 6502
(destination port). Het antwoord kan gestuurd worden naar poort 32897
(source port).
Een groot aantal poorten zijn officieel vastgelegd. Meestal zijn dit poortnummers < 1024. Dit
zijn de zogenaamde well-known ports:
Well known ports zijn vastgelegde definities van poortnummers en de
daaraan gekoppelde services. Vastgelegd in RFC1700.
Enkele voorbeelden:
20/21 | FTP | 80 | HTTP |
22 | SSH | 110 | POP3 |
23 | Telnet | 443 | HTTPS |
25 | SMTP | 6502 | NetAtom |
Een complete lijst van vastgelegde well-known ports is te vinden op het internet en wel op
"http://www.ietf.org/rfc/rfc1700.txt" .
Op deze site zijn overigens alle rfc's te vinden. In deze rfc's
liggen alle afspraken vast die gelden voor het Internet verkeer. Het
lezen en begrijpen van deze rfc's is overigens een vak apart.
5. De Atom en TCP/IP
Wat kunnen we met de Atom en TCP/IP beginnen? Op het moment nog niet veel. De echte Atom heeft nog
geen software om via TCP/IP te communiceren. Ook voor de Atom-in-PC
en de Atom emulatoren zijn er nog geen TCP/IP communicatiemiddelen.
Maar er is hoop: Kees van Oss wil wel proberen om via een seriele
poort, en wellicht via een netwerkkaart ooit TCP/IP te implementeren
op een echte Atom. Op het Internet zijn overigens al verschillende
projecten in een ver gevorderd stadium om TCP/IP stacks voor 6502
microprocessoren aan de praat te krijgen. Vooral op Commodore en
Atari platformen schijnt er al veel te zijn.
Toch kunnen we met de Atom-in-PC wel wat spelen met TCP/IP. Op de clubavond heb ik een
NetAtom server gedemonstreerd. In een PC met Atomkaart draait een
klein programma dat op verbinding wacht van een andere PC, de client.
Op deze client PC draait een speciale versie van het Atom-in-PC
terminal programma. Deze versie communiceert namelijk niet via de ISA
bus met de Atom, maar via het netwerk. In onderstaande listing is het
server programma weergegeven:
/* atomserver.c */
#include <asm/io.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#define BASEPORT 0x31C
main()
{
int cont,create_socket,new_socket,addrlen;
unsigned int b;
int bufsize = 32;
unsigned char *buffer = malloc(bufsize);
struct sockaddr_in address;
printf("Atom server starting\n");
/*
Get access to the ports */
if
(ioperm(BASEPORT, 4, 1)) {perror("ioperm"); exit(1);}
if
((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
printf("The socket was created\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(6502);
if
(bind(create_socket,(struct sockaddr *)&address,sizeof(address))
== 0)
printf("Binding Socket\n");
listen(create_socket,3);
printf("Waiting for client\n");
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(create_socket,(struct sockaddr
*)&address,&addrlen);
if
(new_socket > 0){
printf("The Client %s is
connected...\n",inet_ntoa(address.sin_addr));
}
strcpy(buffer, "Welcome to NetAtom server\n");
send(new_socket,buffer,bufsize,0);
do{
recv(new_socket,buffer,bufsize,0);
if (buffer[0] < 0x80)
{ //
read from port
buffer[0]=inb(BASEPORT+buffer[0]);
}
else
{ //
write to port
outb(buffer[1],
BASEPORT+(0x7F&buffer[0]) );
}
send(new_socket,buffer,1,0);
}while(strcmp(buffer,"/q")); //user ‘q’ to quit
close(new_socket);
close(create_socket);
/*
We don't need the ports anymore */
if
(ioperm(BASEPORT, 4, 0)) {perror("ioperm"); exit(1);}
printf("Atom server shut down\n");
}
Het
client gedeelte ziet er als volgt uit:
/*
atomio.h, included from atom.c */
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
int
create_socket;
int
bufsize = 32;
// char
*buffer=malloc(bufsize);
struct
sockaddr_in address;
unsigned
int readport(int port)
{
char
buffer[bufsize];
buffer[0]=port;
buffer[1]=0x00;
send(create_socket,
buffer, 2, 0);
recv(create_socket,
buffer, bufsize, 0);
return(buffer[0]);
}
void
writeport(unsigned char data, int port)
{
char
buffer[bufsize];
buffer[0]=port+0x80;
buffer[1]=data;
send(create_socket,
buffer, 2, 0);
recv(create_socket,
buffer, bufsize, 0);
}
void
openatom(char *serveraddr)
{
char
buffer[bufsize];
/* Set
up TCP connection to server */
printf("Atom
client starting\n");
if
((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
printf("The
Socket was created\n");
address.sin_family
= AF_INET;
address.sin_port
= htons(6502);
inet_pton(AF_INET,
serveraddr, &address.sin_addr);
if
(connect(create_socket,(struct sockaddr *)&address,sizeof(address))
== 0)
printf("The
connection was accepted with the server
%s...\n",inet_ntoa(address.sin_addr));
recv(create_socket,
buffer, bufsize, 0);
printf("%s",
buffer);
/*
initialize the atom */
writeport(0xB4, 3);
writeport(0x0F,
3);
usleep(100000);
writeport(0x0E,
3);
usleep(100000);
writeport(0x0F,
3);
}
int
readbyte(void)
{
while(!(readport(2)
& 0x20)) ;
return
readport(0);
}
int
sendbyte(int byte)
{
while(!(readport(2)
& 0x02)) ;
writeport(byte,
1);
return(byte);
}
void
closeatom(void)
{
char
buffer[bufsize];
buffer[0]='/'; buffer[1]='q';
send(create_socket, buffer, 2, 0);
recv(create_socket,
buffer, bufsize, 0);
close(create_socket);
printf("Atom client shut down\n");
}
void
resetatom(int msg)
{
if
(msg)
{
printf("\n\n\n");
printf("###################################\n");
printf("#
PRESS ANY KEY TO RESET THE ATOM #\n");
printf("###################################\n");
getchar();
}
writeport(0x0E,
3);
usleep(100000);
writeport(0x0F,
3);
}
Het schrijven van TCP/IP programma's is redelijk eenvoudig. Bovenstaande
voorbeelden laten al zien dat er geen enorme lappen code nodig zijn.
Deze voorbeelden zijn overigens gericht op een Linux platform.
Wanneer we echt met de Atom gaan browsen weten we nog niet, maar de basis van
de communicatie moet wel enigermate verduidelijkt zijn.