Web51 TCP sockets |
Hlavní vlastností tohoto systému je řízení pomocí událostí. Nelze například napsat proceduru zpracovávající ve smyčcce příchozí znaky a využívající procesu na pozadí, který tyto znaky "dodává". Web51 se chová spíše jako ten proces na pozadí, který po přijetí znaku volá proceduru a ta zpracovává znak. Zpracování znaku je obvykle řízeno několika stavovými automaty, které na základě přijatého znaku přechází mezi jednotlivými stavy. Např. stavový automat pro http má stavy očekávající postupně příchod znaků 'G' 'E' 'T' ' ', po kterém se přechází na režim výpočtu indexu (sumy) do souborového systému.
Chování TCP stacku je ovlivňováno nastavením několika konfiguračních konstat.
; "telnet" .global STACK1MODE .equ STACK1MODE, RESENDMODE .global ETHRETRY1 .equ ETHRETRY1, 5*50 ; timeout = 50 s .global PORT1 ; local port .equ PORT1, 23 .global PORT3 ; remote port .equ PORT3, 23 ; "http" .global STACK2MODE .equ STACK2MODE, NORESENDMODE .global ETHRETRY2 .equ ETHRETRY2, 5*2 ; timeout = 2 s .global PORT2 ; local port .equ PORT2, 80
V první řadě jsou to konstanty STACKxMODE s platnými hodnotami RESENDMODE a NORESENDMODE ovlivňující chování TCP stacku z hlediska potvrzování odesílaných dat. RESENDMODE se chová z hlediska TCP korektněji, data se postupně tak jak je protistrana potvrzuje odmazávají z vysílacího bufferu. Nepotvrzená data zůstávají v bufferu a je možno je znovu opakovaně vyslat. Vysílací buffer má omezenou velikost a např. procedura sendchar omezuje jeho velikost na cca 1280 byte. Při překročení tohoto limitu je buffer vyslán a ukazatelé do něj zresetovány. Tento režim je proto vhodný např. na přenosy dat ze sériového kanálu, kdy do TCP paketu kopírujeme data z bufferu sériového kanálu pouze v případě, že je v něm místo. Pro přenos dat, kdy není možno tuto přenášenou velikost dat regulovat, musíme použít druhý režim NORESENDMODE. Tento režim podporuje funkci "vystřel a zapoměň", data po vyslání z bufferu jsou automaticky potvrzena, v případě potřeby rozsegmentována do několika TCP paketů a poslední paket nese příznak FIN. Tento režim je tedy vhodný na vysílaní dat typu www stránek, kdy je možno špatně přenesená data zahodit a celou komunikaci zopakovat od začátku.
Ve druhé řadě je to nastavení konstant ETHRETRYx určujících timeout pro jednotlivé TCP stacky.
Ze stacku 2 nelze navazovat aktivní spojení.
TCP stack při své činnosti volá v závislosti na stavu TCP spojení celkem tři callback procedury. První z nich open_stack je volána při otevření TCP spojení. Lze pomocí ní provést např. inicializaci příslušné procedury, zpracovávající data z TCP spojení. Druhá z nich process_stack je volána vždy když přišla data z TCP spojení, popř. přišlo potvrzení odeslaných dat. Tato procedura zpracovává přijatá data a rovněž předává data do TCP stacku. Třetí z nich close_stack je volána při ukončení spojení.
.text .global open_stack1 .global process_stack1 .global close_stack1 open_stack1: ret process_stack1: ljmp telnet close_stack1: ljmp close_telnet .global open_stack2 .global process_stack2 .global close_stack2 open_stack2: ljmp open_http process_stack2: ljmp http close_stack2: ret
Na výše uvedené ukázce kódu, vyjmuté, stejně jako předchozí ukázka konfiguračních konstant, ze souboru www8051.asm z ukázkového projektu serial, je vidět přiřazení těchto callback procedur reálným procedurám obsluhujícím přenos TCP<->sériový kanál a obsluhujícím protokol http.
Zobrazme si na příkladu obsluhy právě přenosu sériového kanálu přes TCP protokol funkci callback procedury telnet Do callback procedury process_stack obsluhující vlastní přenos dat po TCP jsou předávány dva parametry:
Před voláním procedury process_stack jsou rovněž nastaveny proměnné unwrited, tcpWritePointer a flaghide, sloužící k zápisu dat do TCP stacku. Uživateli jsou však obvykle skryty funkcemi umožňujícími zápis do TCP stacku, jakými jsou např. sendchar, sendDecb, sendHexb, sNibl, send_string.
Na rozdíl od zápisu do TCP stacku, systém Web51 nedisponuje znakovými funkcemi pro čtení s TCP stacku. Zpracování přijatého paketu je na základě proměnných data_addr a data_len plně v režii uživatele.
Nejprve si zkontrolujeme, zda jsou v přijatém paketu data ke zpracování a zazálohujeme si předávanou délku dat.
telnet: ;;send max. data_len bytes to serial line mov a,data_len+1 ;LSB mov workreg+3,a ;LSB mov workreg+2,data_len ;MSB orl a,data_len ;MSB jz sendTelnetDta
Z bufferu obvodu RTL8019AS překopírujeme část přijatého paketu ke zpracování do pracovního bufferu buf v procesoru.
tgetbuf: mov Timeout1,#ethtiming ;restart retry timer ;; Retry1 = ETHRETRY1; mov Retry1,#ETHRETRY1 setb flag1retry ;; NEW data in packet, send delayed Ack LCALL pcode ;; copy_r2s (buf, data_addr, sizeof(buf)); .pcode pr2s BYTE buf, @data_addr, #BYTE sizeofbuf ;copy telnet data ;; data_addr += sizeof(buf); .pcode paddwi BYTE data_addr, #BYTE sizeofbuf .byte 0 mov R0,#buf-1
Překopírovaná data zpracujeme. V případě procedury telnet celkem jednoduše, přesuneme je byte za bytem do vyrovnávací paměti sériového kanálu. Je-li paměť sériového kanálu plná, zpracování předčasně ukončíme.
tnxtin:inc R0 mov a,#(buf + sizeofbuf) xrl a,R0 jz tgetbuf mov a,data_len jnz tdata mov a,data_len+1 jnz tdata sjmp tallsend tdata: mov a,@r0 lcall xputchar jz ttimeout ;; data_len--; mov a,data_len+1 ; LSB dec a mov data_len+1,a cjne A,#0xFF,sndx dec data_len ; MSB sndx: sjmp tnxtin
Potvrdíme protistanici pomocí volání AckBytes data která jsme z předaného TCP paketu zpracovali.
ttimeout: ;; workreg -= data_len; mov r0,#workreg+3 clr C mov a,@r0 subb a,data_len+1 mov @r0,a dec r0 mov a,@r0 subb a,data_len mov @r0,a tallsend: ; Acknowledge only processed data ;; tx_eth_pkt.pkt.ip.ipdata.tcp.tcpheader.Ack = ;; rcvSeq + sendbytes; mov R7,workreg+3 ;LSB mov R6,workreg+2 ;MSB lcall AckBytes
TCP spojení je plně duplexní, proto odpověd, nesoucí potvrzení zpracování přijatých dat, může nést data v opačném směru. Je-li ve vysílaném paketu místo (musíme brát ohled na nastavený režim RESENDMODE), doplníme jej daty z bufferu sériového kanálu. V obvodu RTL8019AS se celý vysílaný paket uchovává pro případné znovuvyslání při chybě TCP/IP přenosu. Na rozdíl od prvních implementací TCP stacku ve Web51 jsou proto data zpracovaná dvojicí volání procedur getchar/sendchar z bufferu sériového kanálu odstraněna. Nečeká se s jejich odstraněním na potvrzení přijetí protistranou.[5]
sendTelnetDta: MOV A,tcpWritePointer ; MSB anl A,#0xFC ; send data only ; if tcpWritePointer %lt; 0x0400 jnz tnodata ;; jsou-li v bufferu nejaka data vysli je jnb rxint,tnodata lcall getchar lcall sendchar sjmp sendTelnetDta tnodata: ret
Po návratu z procedury process_stack jsou do vysílaného paketu vykopírovány případné vyrovnávací buffery procedury sendchar, doplněny TCP příznaky, suma, ... a paket je odeslán.
[5] V režimu NORESENDMODE nemusíme na délku vysílaného paketu brát ohled, vysílaná data se v případě potřeby vyšlou v několika paketech, po návratu z procedury process_stack je však poslední odesílaný paket označen příznakem FIN a spojení je uzavřeno.
POPIS Web51 | NOVINKY | FAQ | OBJEDNÁVKA | DOWNLOAD |
(c)Copyright 2000, 2001, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz Final applications of the Web51 : www.HWgroup.cz |