TCP-IP For TI 89
TCP-IP For TI 89
POSTDIPLOMSKI STUDIJ
IMPLEMENTACIJA PROTOKOLA
TCP/IP
TI89 I TI92+
UVOD
Iako je izvorni kod dug oko 40 kilobajta, GNU C se pokazao kao izvanredan
optimizator, pa je prevedeni kod, uz isključene testne poruke dug nešto manje od 8
kilobajta.
FIZIČKI SLOJ
Port $60000C: Bit 6 omogućava direktni pristup portu, bitovi 3-0 omogućuaju
interapt respektivno u slučaju greške, bilo kakve aktivnosti linka, praznog bafera za
slanje i primljenog novog bajta
Port $60000D: Bit 7 indicira grešku, bit 6 indicira da je bafer za slanje prazan,
bit 5 indicira da imamo bajt u prijemnom baferu, bit 4 da je zahtijevan autointerapt
Port $60000E: Bit 3 čitanje s bijele linije, bit 2 čitanje s crvene linije, bit 1
upis u bijelu liniju ako je dopušten direktan prisup, bit 0 upis u crvenu liniju ako je
dopušten direktan prisup
Port $60000F: cijeli bajt koji šaljemo na link ili čitamo s njega
Sivi GraphLink se može preko Null modem kabla i gender changera povezati s
standardnim modemom, ali to još nije isprobano. Za sada je kao cilj postavljeno da
aplikacija radi sa direktnom vezom.
PROGRAMSKE DEKLARACIJE
Radi olakšanja poziva procedura kao parametara procedura definisan je tip Procref.
#define P(x) x
typedef void ( *Procref ) P((void *s, Byte *dp, int len ));
typedef void ( *Procrefv ) P(( void ));
Iako se koristi isključivo serijska veza, IP zaglavlje sadrži i Eternet adresu, pa je i ona
deklarisana
struct Ethernet_Address {
Word w[ 3 ];
};
/* Ethernet zaglavlje */
struct eth_Header {
struct Ethernet_Address destination; /* 48 bits = 6 bytes */
struct Ethernet_Address source; /* 48 bits = 6 bytes */
Word type; /* 16 bits = 2 bytes */
}; /* total 14 bytes */
struct tcp_Header {
Word srcPort;
Word dstPort;
Longword seqnum;
Longword acknum;
Word flags;
Word window;
Word checksum;
Word urgentPointer;
};
struct tcp_Pseudoheader {
IP_Address src; /* 4 bytes */
IP_Address dst; /* 4 bytes */
Byte mbz; /* mora biti 0. 1 byte */
Byte protocol; /* 6 = tcp. 1 byte */
Word length; /* 2 bytes */
Word checksum; /* 2 bytes */
}; /* 14 bytes */
struct tcp_Socket {
struct tcp_Socket * next; /* pokazivac na sljedeci soket */
short state; /* stanje veze */
Procref dataHandler; /* pozvano s podacima koji dolaze */
struct Ethernet_Address hisethaddr; /* ethernet adresa udaljenog */
IP_Address hisaddr; /* internet adresa udaljenog */
Word myport, hisport; /* tcp portovi za ovu konekciju */
Longword acknum, seqnum; /* potvrdjeni i sekvencni broj */
Longword timeout; /* timeout, u milisekundama */
short unhappy; /* flag, retransmisije semenata */
Word flags; /* flegovi zadnjeg paketa */
short dataSize; /* broj bajtova podataka koji se salju */
Byte data[ TCP_MAXDATA ]; /* podaci koji se salju */
};
Byte * sed_IsPacket() {
unsigned char uc;
#ifdef DEBUG_SED
11
unsigned char * p;
#endif
static int end_count = 0;
static int b_esc_flag = 0;
static unsigned char lastuc=0;
Longword delay;
if (p_begin_packet==NULL) {
p_begin_packet = &recvbuffer[0];
end_count=0;
}
if (p_recv_next==NULL) {
p_recv_next = &recvbuffer[0];
end_count=0;
}
if ((Longword)p_recv_next>
(Longword)&recvbuffer[BUFFERSIZE-1]) {
p_begin_packet=&recvbuffer[0];
p_recv_next=&recvbuffer[0];
puts("Full buffer");
OSLinkReset();
if( b_esc_flag ) {
switch( uc ) {
case T_FR_ESC:
*p_recv_next++ = FR_ESC;
break;
case T_FR_END:
*p_recv_next++ = FR_END;
break;
default:
*p_recv_next++ = uc;
}
b_esc_flag = 0;
} else {
switch( uc ) {
case FR_ESC:
b_esc_flag = 1;
break;
case FR_END:
++end_count;
if ((end_count==2)&&
(p_begin_packet==p_recv_next)) {
end_count=1;
OSLinkReset();
if( end_count == 2 ) {
p_recv_next = &recvbuffer[ 0 ];
end_count = 0;
return p_begin_packet;
} else {
return ( Byte * ) 0;
}
}
12
int ResetBuffer()
{
p_begin_packet=NULL;
p_recv_next==NULL;
MREŽNI SLOJ
<------------------------------------------32 bits------------------------------------->
Version IHL Type of service Total length
Identification DF/MF/Fragment offset
Time to live Protocol Header checksum
Source address
Destination address
Options
<------------------------------------------32 bits------------------------------------->
vht Length
identification Frag
ttlProtocol Checksum
Source
Destination
Neki podaci su dakle pakovani u 16-bitne riječi, a opcije ne postoje. Neki od
podataka se ignorišu.
13
Prijem datagrama se vrši u glavnoj petlji funkcije tcp. Ona kao parametar ima
pokazivač na funkciju application koja će se pozivati u stanju kada se ne vrši obrada
primljenih datagrama.
Funkcija se vrti u “beskonačnoj” for (;;) petlji iz koje se izlazi kada varijabla
EndProgram ima vrijednost različitu od nule (a to će se postići kada se pritisne ESC
taster). Pozivom gore opisane funckije sed_IsPacket se dobije početna adresa SLIP
frejma. Pošto SLIP dopušta da se njim prenosi jedino IP protokol, to će ujedno značiti
i početnu adresu IP datagrama. Ako je ta adresa jednaka nuli, to je idle stanje i
iskoristiti će se za unos korisničke komande i retransmisiju datagrama.
Procrefv application;
{
struct in_Header * ip;
Longword timeout, start;
timeout = 0L;
for(;;) {
if (EndProgram) break;
start = ( Longword ) MsecClock();
/* Imamo li paket? */
ip = ( struct in_Header * ) sed_IsPacket();
if( ip == ( struct in_Header * ) 0 ) {
/* Nemamo ga. */
if( MsecClock() > timeout ) {
/* Anything to retransmit? */
tcp_Retransmitter();
/* Set next transmit time */
timeout = MsecClock() + tcp_RETRANSMITTIME;
}
/* Nema posla, pa neka korisnik unese komandu. */
application();
continue;
}
if ( (IP_PROTOCOL( ip )) == 6) tcp_Handler(ip);
14
/* reciklaza */
recycle:
}
return 1;
}
return sum;
}
Funckija checksum poziva funkciju lchecksum a zatim sabira višu i nižu riječ
ovako dobijene sume po modulu 65536 (0xFFFF).
/* ----- racuna Word checksum ------------------------------------ */
/* internet zaglavlje */
pkt -> in.vht = ( 0x4500 ); /* verzija 4, duzina 5, tos 0 */
pkt -> in.identification = ( tcp_id++ );
pkt -> in.frag = 0;
pkt -> in.ttlProtocol = (( 250 << 8 ) + 6 );
pkt -> in.checksum = 0;
pkt -> in.source = ( local_IP_address );
pkt -> in.destination = ( s -> hisaddr );
pkt -> in.checksum = ((Word ) ~ checksum( ( Word * ) &pkt -> in,
sizeof( struct in_Header )));
/* racunaj tcp checksum */
ph.src = pkt -> in.source;
ph.dst = pkt -> in.destination;
ph.mbz = 0;
ph.protocol = 6;
ph.length = (( pkt -> in.length ) - sizeof( struct in_Header ));
lw = lchecksum( ( Word * ) &ph, sizeof( ph ) - 2 );
while( lw & 0xFFFF0000L )
lw = ( lw & 0xFFFFL ) + (( lw >> 16L ) & 0xFFFFL );
lw += lchecksum( ( Word * ) &pkt -> tcp,
( ph.length ));
while( lw & 0xFFFF0000L )
lw = ( lw & 0xFFFFL ) + (( lw >> 16L ) & 0xFFFFL );
pkt -> tcp.checksum = ( ~ ( Word )( lw & 0xFFFFL ));
#ifdef DEBUG_TCP
tcp_DumpHeader( &pkt -> in, &pkt -> tcp, "Sending" );
#endif
sed_Send( ( pkt -> in.length ));
}
Brisanje soketa iz liste vrši se funkcijom tcp_Unthread. Ona prođe kroz cijelu
listu i poveže pokazivače ostalih soketa da više ne pokazuju na dati soket.
/* ----- Izbaci soket iz liste ako je tu ------ */
TRANSPORTNI SLOJ
f = ( tp -> flags );
printf("%x",f);
}
#endif
19
active OPEN
CLOSED -----------
create TCB
snd SYN
passive OPEN CLOSE
------------ ----------
create TCB delete TCB
CLOSE
LISTEN ----------
delete TCB
rcv SYN SEND
----------- -------
snd SYN,ACK snd SYN
CLOSE
------- ESTAB
snd FIN
CLOSE rcv FIN
------- -------
snd FIN snd ACK
FIN CLOSE
WAIT-1 WAIT
rcv FIN
rcv ACK of FIN ------- CLOSE
-------------- snd ACK -------
x snd FIN
Iz stanja FIN_WAIT2 (druga strana se složila za prekid, što je u kodu dato kao
case TS_RFIN) ako su brojevi sekvenci u redu se prelazi u stanje TIMED_WAIT.
#ifdef DEBUG_TCP
else puts( "got close" );
#endif
tcp_Unthread( s );
return;
}
switch( s -> state ) {
case TS_LISTEN:
/* Inicialno stanje of a Listen porta */
if( flags & TCPF_SYN ) {
/* Ocekujemo nazad SYN */
s -> acknum = ( tp -> seqnum ) + 1;
s -> hisport = ( tp -> srcPort );
s -> hisaddr = ( ip -> source );
s -> flags = TCPF_SYN | TCPF_ACK;
tcp_Send( s );
s -> state = TS_RSYN;
s -> unhappy = True;
s -> timeout = tcp_TIMEOUT;
#ifdef DEBUG_TCP
puts("Syn");
#endif
}
break;
case TS_SSYN:
/* Inicialno stanje Open porta */
if( flags & TCPF_SYN ) {
s -> acknum++;
s -> flags = TCPF_ACK;
s -> timeout = tcp_TIMEOUT;
if(( flags & TCPF_ACK )
&& ( tp -> acknum )
== ( s -> seqnum + 1 ) ) {
puts( "--- Open! ---\n" );
s -> state = TS_ESTAB;
s -> seqnum++;
s -> acknum = ( tp -> seqnum )+ 1;
s -> unhappy = False;
} else {
s -> state = TS_RSYN;
}
} else {
#ifdef DEBUG_TCP
puts( "Sent Syn, didn't get Syn back\n" );
#endif
/* Poluotvorena konekcija. */
s -> flags = TCPF_RST;
s -> seqnum = ( tp -> acknum );
tcp_Send( s );
#ifdef DEBUG_TCP
puts("Sent RST!\n" );
#endif
/* Ne ocekujemo odgovor. Spremi se da posaljes SYN kad se desi
timeout. */
s -> flags = TCPF_SYN;
s -> timeout = tcp_TIMEOUT;
s -> seqnum = 0; /* Pocni */
/* Ostani u SYNSENT cekaj timeout. */
}
break;
case TS_RSYN:
if( flags & TCPF_SYN ) {
s -> flags = TCPF_SYN | TCPF_ACK;
tcp_Send(s);
s -> timeout = tcp_TIMEOUT;
#ifdef DEBUG_TCP
puts(" retransmit of original syn\n");
#endif
}
if(( flags & TCPF_ACK )
&& ( tp -> acknum )
== ( s -> seqnum + 1L ) ) {
s -> flags = TCPF_ACK;
tcp_Send( s );
23
s -> seqnum++;
s -> unhappy = False;
s -> state = TS_ESTAB;
s -> timeout = tcp_TIMEOUT;
#ifdef DEBUG_TCP
puts( "Synack received - connection established\n" );
#endif
} else {
#ifdef DEBUG_TCP
puts( "Wrong syn. ");
#endif
}
break;
case TS_ESTAB:
if(( flags & TCPF_ACK ) == 0 ) return;
/* procesiraj ack vrijednost u paketu */
diff = ( int )( ( tp -> acknum )- s -> seqnum );
if( diff > 0 ) {
/* diff vrijednost je broj bajtova MOJIH podataka koje
udaljeni racunar potvrdjuje. */
if( diff > TCP_MAXDATA ) diff = TCP_MAXDATA;
else {
Move( &s -> data[ diff ],
&s -> data[ 0 ],
TCP_MAXDATA - diff );
}
case TS_SFIN:
if(( flags & TCPF_ACK ) == 0 ) return;
diff = ( int )( ( tp -> acknum )
- s -> seqnum - 1 );
s -> flags = ( Word )( TCPF_ACK | TCPF_FIN );
if( diff == 0 ) {
s -> state = TS_AFIN;
s -> flags = TCPF_ACK;
#ifdef DEBUG_TCP
puts("finack received.\n");
#endif
}
tcp_ProcessData(s, tp, len);
break;
case TS_AFIN:
s -> flags = TCPF_ACK;
tcp_ProcessData( s, tp, len );
break;
case TS_RFIN:
if( ( tp -> acknum ) == (s -> seqnum + 1) ) {
s -> state = TS_TIMEWT;
s -> timeout = tcp_TIMEOUT;
}
break;
case TS_LASTACK:
if( ( tp -> acknum ) == (s -> seqnum + 1) ) {
s -> state = TS_CLOSED;
s -> unhappy = False;
s -> dataSize = 0;
if( s -> dataHandler != 0 )
( s -> dataHandler )(( void * ) s,
( Byte * ) 0, 0 );
#ifdef DEBUG_TCP
else puts( "got close, no handler\n" );
#endif
tcp_Unthread( s );
#ifdef DEBUG_TCP
puts( "Closed. [626]\n" );
24
#endif
} else {
s -> flags = TCPF_ACK | TCPF_FIN;
tcp_Send( s );
s -> timeout = tcp_TIMEOUT;
#ifdef DEBUG_TCP
puts("retransmitting FIN\n" );
#endif
}
break;
case TS_TIMEWT:
s -> flags = TCPF_ACK;
tcp_Send(s);
}
}
#endif
break;
case TS_SFIN:
x = TS_RFIN;
break;
case TS_AFIN:
x = TS_TIMEWT;
break;
}
s -> state = x;
}
} else {
#ifdef DEBUG_TCP
printf( "diff was negative, %d\n", diff );
#endif
}
s -> timeout = tcp_TIMEOUT;
tcp_Send( s );
}
SESIJSKI SLOJ
Procref datahandler;
{
Tamo gdje TI89 radi kao server, predviđeno je otvaranje veze s tcp_Listen.
Soket se prebacuje u stanje LISTEN i inicijaliziraju njegova polja. Sada se soket ne
šalje, jer je ovo pasivna konekcija, očekuje se otvaranje s druge strane.
Procref datahandler;
Longword timeout;
{
s -> state = TS_LISTEN;
/* Dodaj ga u listu */
s -> unhappy = 0;
s -> dataSize = 0;
s -> state = TS_CLOSED;
PREZENTACIONI SLOJ
27
Svi protokoli višeg nivoa koji će biti implementirani koriste ASCII kod. TI89
koristi modifikovanu verziju ASCII koda koja se uglavnom razlikuje po karakterima
sa kodom ispod 32. TI89 ima znatno više grafičkih znakova u odnosu na ASCII, jer su
mu potrebni za prikaz matematičkih operacija. Nažalost, u ROM-u nisu
implementirane standardne C funkcije putc, puts i printf, esencijalne za prikaz ASCII
podataka na ekranu, pa su napisane posebno. U tome pomaže činjenica da je sprintf
implementiran. Funkcija putc brine da se karakter prikaže na pravom mjestu iza
prethodnog, a u slučaju potrebe i skrolira ekran. Puts štampa string, a printf
formatizovano štampa više različitih argumenata.
static int __x = 0, __y = 0;
Pored ASCII podataka, FTP može da prenosi i binarne datoteke. TI89 nema
datoteke u klasičnom smislu te riječi, na spoljnjem, magnetnom mediju. Umjesto toga
postoje varijable koje se čuvaju u osnovnoj ili Flash memoriji. Njihov sadržaj se čuva
baterijama. Funkcijom CreateFile se alocira maksimalni dopušteni prostor u RAM-u
za varijablu. Na početku njenog sadržaja nalazi se dužina varijable. Sa Hlock
zabranjujemo premještanje te varijable iz memorije. Funkcijom AppendCharToFile se
karakter stavlja na kraj iskorištenog prostora te varijable i ažurira dužina.
AppendBlockToFile obavlja isto sa više karaktera. CloseFile na kraj iskorištenog
prostora stavlja signaturu koja znači da je varijabla string tipa , s HeapUnlock
dopustimo pomjeranje bloka i promijenimo njegovu dužinu da oslobodimo
neiskorišteni prostor.
28
void CloseFile(HANDLE h)
{
AppendCharToFile(h,0); AppendCharToFile(h,0x2D);
HeapUnlock(h);
HeapRealloc(h,*(unsigned*)HeapDeref(h)+3);
}
APLIKATIVNI SLOJ
USER anonymous
PASS [email protected]
LIST
RETR program.zip
QUIT
USER johnsmith
PASS idontknow
LIST
RETR 2
QUIT
Ove komande navedu E-mail adrese pošiljaoca i primaoca, a zatim iza komande
DATA slijede redovi poruke, pri čemu i oni mogu imati specijalni sadržaj. Poruka se
završava redom koji sadrži tačku. Komanda QUIT šalje sve poruke i prekida vezu.
ftp_Abort()
{
tcp_Abort(ftp_ctl);
tcp_Abort(ftp_data);
}
if ( dp == 0 ) {
tcp_Abort(ftp_data);
return;
}
do {
i = len;
if ( i > sizeof data ) i = sizeof data;
Move(dp, data, i);
len -= i;
bp = data;
while ( i-- > 0 ) {
c = *bp++;
if ( c != '\r' ) {
if ( c == '\n' ) {
ftp_cmdbuf[ftp_cmdbufi] = 0;
if (remoteport==21)
ftp_commandLine();
else
printf("> %s\n", ftp_cmdbuf);
ftp_cmdbufi = 0;
} else if ( ftp_cmdbufi < (SIZECMDBUF)-1 ) {
ftp_cmdbuf[ftp_cmdbufi++] = c;
}
}
}
} while ( len > 0 );
}
case ftp_StateINCOMMAND:
if ( ftp_cmdbuf[3] == '-' )
ftp_rcvState = ftp_StateRCVRESP;
case ftp_StateRCVRESP:
31
Ova aplikacija nije multitasking, ali ipak korisnička akcija ne blokira prijem i
obradu paketa. Obrada svih protokola koji rade po principu naredba-Enter-odgovor
(dakle osim Telneta) se vrši u funkciji ftp_application. Komanda Osdequeue čita
pritisnuti taster bez usporavanja aplikacije. Ako je taj taster ESC (kod 264) veza se
zatvara i ako ima fajla u koji upisujemo zatvaramo i njega, te TCP/IP konekcije.
Indicira se varijabla EndProgram koja znači kraj programa.
tcp_Close(ftp_ctl);
EndProgram=1;
}
}
switch (ftp_rcvState) {
case ftp_StateGETCMD:
getcmd:
if ( i != -1 ) {
ftp_outbuf[ftp_outbuflen] = 0;
if (i==176) i=64;
if (i==168) i=35;
switch (i) {
case 257:
if ( ftp_outbuflen > 0 ) {
ftp_outbuflen--;
putc(127);
putc(' ');
}
break;
case '\r':
32
case '\n':
puts("\n");
dp = &ftp_outbuf[ftp_outbuflen];
goto docmd;
default:
if ( i >= ' ' && ftp_outbuflen < OUTBUFSIZE ) {
ftp_outbuf[ftp_outbuflen++] = i;
putc(i);
}
}
}
break;
case ftp_StateIDLE:
ftp_rcvState = ftp_StateGETCMD;
ftp_outbuflen = 0;
puts("Command> ");
goto getcmd;
docmd:
*dp++ = '\r';
*dp++ = '\n';
if(( strncmp( ftp_outbuf, "RETR ", 5 ) == 0 )
|| ( strncmp( ftp_outbuf,"retr ", 5 ) == 0 )){
if (! hreturnfile)
hreturnfile=CreateFile("received");
}
if(( strncmp( ftp_outbuf, "LIST ", 5 ) == 0 )
|| ( strncmp( ftp_outbuf,"list ", 5 ) == 0 )){
hreturnfile=0;
}
ftp_outbuflen = (unsigned long)dp - (unsigned long)ftp_outbuf;
ftp_outbufix = 0;
ftp_rcvState = ftp_StateINCOMMAND;
/* nastavlja */
case ftp_StateINCOMMAND:
i = ftp_outbuflen - ftp_outbufix;
if ( i > 0 ) {
i = tcp_Write(ftp_ctl, &ftp_outbuf[ftp_outbufix], i);
ftp_outbufix += i;
tcp_Flush(ftp_ctl);
}
/* fall through */
case ftp_StateRCVRESP:
break;
}
}
do {
i = len;
if ( i > sizeof data ) i = sizeof data;
Move(dp, data, i);
len -= i;
bp = data;
while ( i-- > 0 ) {
c = *bp++;
if (c=='\n') printf("\n");
else if (c>=' ') putc(c);
}
} while ( len > 0 );
KORISNIČKA APLIKACIJA
port = 0x4200;
/* postavi varijable stanja */
ftp_rcvState = ftp_StateRCVRESP;
ftp_cmdbufi = 0;
switch (protocol) {
case 1:
34
LCD_BUFFER savescr;
LCD_save(savescr); /* Sacuvaj ekran */
EndProgram=0;
queue=kbd_queue();
clrscr();
OSLinkReset(); /* Pripremi Graphlink */
OSFreeTimer(6); /* Pripremi tajmer */
OSRegisterTimer(6,32000);
xmitbuffer=malloc(BUFFERSIZE); /* Alociraj memoriju */
recvbuffer=malloc(BUFFERSIZE);
ftp_ctl=malloc(sizeof(struct tcp_Socket));
ftp_data=malloc(sizeof(struct tcp_Socket));
ftp_cmdbuf=malloc(SIZECMDBUF);
ftp_outbuf=malloc(OUTBUFSIZE); /* Prozivaj dijalog dok se ne odabere ESC */
while (connect_dialog(&local_IP_address, &remote_IP_address,email,&protocol)==1)
{ EndProgram=0;
hreturnfile=0;
FontSetSys(F_4x6); /* Najmanji font */
tcp_Init(); /* Inicijaliziraj TCP */
applayer(remote_IP_address,ftp_dataHandler,protocol); /* Odredi protokol*/
}
free(xmitbuffer); /* Oslobodi memoriju */
free(recvbuffer);
free(ftp_ctl);
free(ftp_data);
free(ftp_cmdbuf);
free(ftp_outbuf);
MOGUĆA PROŠIRENJA
Kada verzija 2.05 operativnog sistema ovog kalkulatora koja povećava limit
za mašinske/C programe na 24 K, potpuno zamijeni verziju 2.03 program će se moći
proširiti. Potrebno je
Dodati UDP i DNS protokol i hosts tabele da se ne mora raditi isključivo sa IP
adresama
Dodati miniterminal za uspostavljanje SLIP veze
Modemski povezati TI89 za provajderom
Poboljšati prikaz HTML
U Telnetu emulirati neki terminal poput VT100
Pisati Front end aplikacije za navedene portove
Implementirati ICMP i PING kao server i kao klijent
Realizovati FTP slanje
LITERATURA
Andrew S. Tannenbaum, Computer Networks Third Edition, Prientice Hall International, 1996
Geoffrey Cooper, IMAGEN Corporation tinytcp.c - Tiny Implementation of the Transmission
Control Protocol, written March 28, 1986
Željko Jurić, TIGCC Library, Sarajevo 2000
Network Working Group J. RomkeyRequest for Comments: 1055 June l988 A NONSTANDARD
FOR TRANSMISSION OF IP DATAGRAMS OVER SERIAL LINES: SLIP
Network Working Group T. SocolofskyRequest for Comments: 1180 C. Kale Spider Systems
Limited January 1991 A TCP/IP Tutorial
Network Working Group T. Berners-LeeRequest for Comments: 1866 MIT/W3CCategory:
Standards Track D. Connolly November 1995 Hypertext Markup Language - 2.0
Network Working Group J. MyersRequest for Comments: 1939 Carnegie MellonSTD: 53 M.
RoseObsoletes: 1725 Dover Beach Consulting, Inc.Category: Standards Track May 1996 Post
Office Protocol - Version 3
Network Working Group T. Berners-LeeRequest for Comments: 1945 MIT/LCSCategory:
Informational R. Fielding UC Irvine H. Frystyk MIT/LCS May 1996 Hypertext Transfer Protocol
-- HTTP/1.0
Network Working Group A. ContaRequest for Comments: 2463 LucentObsoletes: 1885 S.
DeeringCategory: Standards Track Cisco Systems December 1998 Internet Control Message
Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification
Network Working Group A. GulbrandsenRequest for Comments: 2782 Troll
TechnologiesObsoletes: 2052 P. VixieCategory: Standards Track Internet Software Consortium L.
Esibov Microsoft Corp. February 2000 A DNS RR for specifying the location of services (DNS
SRV)
RFC 768 J. Postel ISI 28 August 1980 User Datagram Protocol
RFC: 793 TRANSMISSION CONTROL PROTOCOL DARPA INTERNET PROGRAM
PROTOCOL SPECIFICATION
Jonathan B. Postel RFC 821 SIMPLE MAIL TRANSFER PROTOCOL
Network Working Group J. PostelRequest for Comments: 854 J. Reynolds ISIObsoletes: NIC
18639 May 1983 TELNET PROTOCOL SPECIFICATION
Network Working Group J. PostelRequest for Comments: 959 J. Reynolds ISIObsoletes RFC: 765
(IEN 149) October 1985 FILE TRANSFER PROTOCOL (FTP)