You are on page 1of 99

http://www.dientuvietnam.net/forums/vi-dieu-khien-avr-55/giao-thuc-tcp-ip-va-web-server-voi-avr-87172/index3.

html
http://codientu.org/threads/mach-ethernet-web-server-voi-atmega-32.5718/page-2

D l trn PIC hay AVR hay bt c micro controller no th c ch cng nh nhau thi (thm ch trn my tnh th cng tng t), ch khc
l i vi PIC th Microchip cung cp y b th vin cho cc giao thc ethernet, ip, arp, udp, tcp, dhcp, http, khng cn phi vit li
nh anh ang lm cho AVR. C ch nh sau:
- Khi ta m my tnh ln, m trnh duyt v g vo a ch ca webserver (PIC hay AVR g cng th), gi s y ta g vo a ch IP nh
sau: http://192.168.1.10
- Sau khi nhn enter th my tnh ca chng ta s gi i mt bn tin request ca giao thc HTTP (Hyper Text Transfer Protocol, giao thc
truyn/nhn ni dung trang web), thng l HTTP Get thng qua giao thc TCP (vi cng TCP c qui nh cho giao thc HTTP l
80) n a ch webserver trn.
- Webserver, y chnh l vi iu khin ca chng ta (PIC hay AVR) nhn c bn tin ny (tt nhin bn tin ny s i qua ht cc lp
giao thc ethernet, IP, TCP ri mi n HTTP). Ti y vi iu khin s c v phn tch bn tin HTTP request ny bit my tnh ang
yu cu ti ni dung trang web no.
- Sau vi iu khin s ly ni dung trang web ny (c son tho theo ngn ng HTML) cha trn trn flash ROM, n cng c th
thm vo trang web mt s thng tin (v d c gi tr t cc sensor cm bin nhit v a vo trong trang web), v gi ton b ni
dung trang web thng qua giao thc TCP tr li cho my tnh. Nu ni dung trang web ln n c th c gi i trn rt nhiu gi tin, v
mi gi tin ch cha ti a 1460 byte d liu m thi.
- My tnh nhn ni dung trang web v trnh duyt s hin th ln cho chng ta thy.
- iu khin board t xa qua web, trn trang web ta c th thit k mt nt nhn chng hn. Khi ta nhn nt ny trn trnh duyt, my
tnh s gi i mt bn tin HTTP na l HTTP Post, trong bn tin ny s cha cc thng tin v trng thi cc nt option hay cc gi tr trong
cc edit text c trn trang web.
- Vi iu khin s nhn bn tin HTTP post ny, phn tch d liu cha trong c p ng tng ng (bt tt relay chng hn) sau
n s gi tr li ln na ni dung trang web cp nht nhng thay i va ri (v d bt reley th trn web s c 1 hnh trn i sang mu
chng hn). Trnh duyt s update ni dung ny ln v ta s thy c tc ng ca thao tc iu khin .
T t anh s vit v gii thch tt c cc hot ng trn AVR, trn PIC cng th nhng cc hm c Microchip cung cp sn m thi.
Khi giao tip vi ENC28J60 qua SPI, ngoi a ch th cn c Operating code iu khin thao tc c/ghi/
Thm nh ngha cc code ny vo file trn (trn dng #endif //ENC28J60_H nh)
Code:
// SPI operation codes
#define ENC28J60_READ_CTRL_REG
#define ENC28J60_READ_BUF_MEM
#define ENC28J60_WRITE_CTRL_REG
#define ENC28J60_WRITE_BUF_MEM
#define ENC28J60_BIT_FIELD_SET
#define ENC28J60_BIT_FIELD_CLR
#define ENC28J60_SOFT_RESET

0x00
0x3A
0x40
0x7A
0x80
0xA0
0xFF

Khai bo a ch bt u v kt thc buffer d liu gi v nhn trn ENC28J60:


Code:
#define
#define
#define
#define

TXSTART_INIT
TXSTOP_INIT
RXSTART_INIT
RXSTOP_INIT

0x0000
0x05FF
0x0600
0x1FFF

//Dia
//Dia
//Dia
//Dia

chi
chi
chi
chi

bat
ket
bat
ket

dau buffer gui


thuc buffer gui
dau buffer nhan
thuc buffer nhan

//Khai bao kich thuoc frame ethernet max va min


#define MAX_FRAMELEN
1518
#define ETHERNET_MIN_PACKET_LENGTH
0x3C
Tip theo, m file enc28j60conf.h, thm vo cc khai bo v IO port s dng iu khin ENC28J60 v mt s thng tin
cu hnh khc (a ch MAC)
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef ENC28J60CONF_H
#define ENC28J60CONF_H
//
//Khai bao cac chan IO cho ENC28J60
#define ENC28J60_CONTROL_DDR
DDRB
#define ENC28J60_CONTROL_PORT
PORTB
#define ENC28J60_SPI_DDR
DDRB
#define ENC28J60_SPI_PORT
PORTB
//
#define ENC28J60_CONTROL_CS
3
#define ENC28J60_CONTROL_RESET
4
#define ENC28J60_SPI_SCK
7
#define ENC28J60_SPI_MISO
6

#define ENC28J60_SPI_MOSI
5
#define ENC28J60_SPI_SS
4
#define ENC28J60_SPI_CS
3
//
//Dinh nghia macro chon chip ENC28J60
#define ENC28J60_CS_LO()
ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
#define ENC28J60_CS_HI()
ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
//
#define ETH_INTERRUPT
INT2_vect
//
#if defined (__AVR_ATmega32__)
#define ETH_INT_ENABLE
GICR |= (1<<INT2)
#define ETH_INT_DISABLE GICR &= ~(1<<INT2)
#endif
#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__)
#define ETH_INT_ENABLE
EIMSK |= (1<<INT2)
#define ETH_INT_DISABLE EIMSK &= ~(1<<INT2)
#endif
// MAC address for this interface
#ifdef ETHADDR0
#define ENC28J60_MAC0 ETHADDR0
#define ENC28J60_MAC1 ETHADDR1
#define ENC28J60_MAC2 ETHADDR2
#define ENC28J60_MAC3 ETHADDR3
#define ENC28J60_MAC4 ETHADDR4
#define ENC28J60_MAC5 ETHADDR5
#else
#define ENC28J60_MAC0 '0'
#define ENC28J60_MAC1 'F'
#define ENC28J60_MAC2 'F'
#define ENC28J60_MAC3 'I'
#define ENC28J60_MAC4 'C'
#define ENC28J60_MAC5 'E'
#endif

#endif // ENC28J60CONF_H
//---------------------------------------------------------------------------Trc ht ta cn 1 hm c v 1 hm ghi d liu vo 1 a ch xc nh trn ENC28J60 qua SPI:
M file enc28j60.c, thm vo cc hm (sau nh thm khai bo hm vo file header enc28j60.h na nh)
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include <avr/io.h>
#include "ntAVRnet.h"
#include "enc28j60.h"
#include "enc28j60conf.h"
#include <avr/pgmspace.h>
//---------------------------------------------------------------------------unsigned char enc28j60SPIRead(unsigned char op, unsigned char address)
{
unsigned char res;
ENC28J60_CS_LO();
SPDR = op | (address & ADDR_MASK);
while(!(SPSR & (1<<SPIF)));
SPDR = 0x00;
while(!(SPSR & (1<<SPIF)));
if(address & 0x80){
SPDR = 0x00;
while(!((SPSR) & (1<<SPIF)));
}
res = SPDR;
ENC28J60_CS_HI();
return res;
}
void enc28j60SPIWrite(unsigned char op, unsigned char address, unsigned char data)
{
ENC28J60_CS_LO();

SPDR = op | (address & ADDR_MASK);


while(!(SPSR & (1<<SPIF)));
SPDR = data;
while(!(SPSR & (1<<SPIF)));
ENC28J60_CS_HI();
}
ENC28J60 chia tp thanh ghi thnh cc bank, ta vit 1 hm set bank thanh ghi:
Trc ht ta khai bo 1 bin kiu char lu bank hin ti (thm vo u file):
Code:
unsigned char Enc28j60Bank;
V vit hm:
Code:
void enc28j60SetBank(unsigned char address)
{
if((address & BANK_MASK) != Enc28j60Bank)
{
enc28j60SPIWrite(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
enc28j60SPIWrite(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
Enc28j60Bank = (address & BANK_MASK);
}
}
phc v cho vic c v ghi buffer d liu, ta vit tip 2 hm c v ghi buffer:
Code:
void enc28j60ReadBuffer(unsigned int len, unsigned char* data)
{
ENC28J60_CS_LO();
SPDR = ENC28J60_READ_BUF_MEM;
while(!(SPSR & (1<<SPIF)));
while(len--)
{
SPDR = 0x00;
while(!(SPSR & (1<<SPIF)));
*data++ = SPDR;
}
ENC28J60_CS_HI();
}
void enc28j60WriteBuffer(unsigned int len, unsigned char* data)
{
ENC28J60_CS_LO();
SPDR = ENC28J60_WRITE_BUF_MEM;
while(!(SPSR & (1<<SPIF)));
while(len--)
{
SPDR = *data++;
while(!(SPSR & (1<<SPIF)));
}
ENC28J60_CS_HI();
}
Da vo c s cc hm ny, ta xy dng cc hm c ghi thanh ghi iu khin, thanh ghi PHY ca ENC28J60:
Code:
unsigned char enc28j60Read(unsigned char address)
{
enc28j60SetBank(address);
return enc28j60SPIRead(ENC28J60_READ_CTRL_REG, address);
}
void enc28j60Write(unsigned char address, unsigned char data)
{
enc28j60SetBank(address);
enc28j60SPIWrite(ENC28J60_WRITE_CTRL_REG, address, data);
}
unsigned int enc28j60PhyRead(unsigned char address)
{
unsigned int data;
enc28j60Write(MIREGADR, address);

enc28j60Write(MICMD, MICMD_MIIRD);
while(enc28j60Read(MISTAT) & MISTAT_BUSY);
enc28j60Write(MICMD, 0x00);
data = enc28j60Read(MIRDL);
data |= enc28j60Read(MIRDH);
return data;
}
void enc28j60PhyWrite(unsigned char address, unsigned int data)
{
enc28j60Write(MIREGADR, address);
enc28j60Write(MIWRL, data);
enc28j60Write(MIWRH, data>>8);
while(enc28j60Read(MISTAT) & MISTAT_BUSY);
}
Cc hm trn cho php truy xut y vo tp thanh ghi ca ENC28J60
Tip theo ta vit tip 2 hm gi v nhn 1 gi tin:
Code:
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
{
enc28j60Write(EWRPTL, TXSTART_INIT);
enc28j60Write(EWRPTH, TXSTART_INIT>>8);
enc28j60Write(ETXNDL, (TXSTART_INIT+len));
enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
enc28j60SPIWrite(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
enc28j60WriteBuffer(len, packet);
enc28j60SPIWrite(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
}
unsigned int NextPacketPtr;
unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet)
{
unsigned int rxstat;
unsigned int len;
if( !enc28j60Read(EPKTCNT) )
return 0;
enc28j60Write(ERDPTL, (NextPacketPtr));
enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
NextPacketPtr = enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0);
NextPacketPtr |= ((unsigned int)enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0))<<8;
len = enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0);
len |= ((unsigned int)enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0))<<8;
rxstat = enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0);
rxstat |= ((unsigned int)enc28j60SPIRead(ENC28J60_READ_BUF_MEM, 0))<<8;
len = ((len<maxlen)?(len) : (maxlen));
enc28j60ReadBuffer(len, packet);
enc28j60Write(ERXRDPTL, (NextPacketPtr));
enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
enc28j60SPIWrite(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
return len;
}
V hm khi ng IC ENC28J60:
c th nhanh chng truy xut thng tin cu hnh khi ng cho ENC28J60, ta lu ton b thng tin ny vo mt array
trong b nh flash cha a ch cc thanh ghi v gi tr khi to tng ng, khai bo array ny trong file enc28j60.c:
Code:
prog_char enc28j60_config[44] PROGMEM = {
ETXSTL, LO8(TXSTART_INIT), //start lo
ETXSTH, HI8(TXSTART_INIT), //start hi
ETXNDL, LO8(TXSTOP_INIT ), //end lo
ETXNDH, HI8(TXSTOP_INIT ), //end hi
ERXSTL,
ERXSTH,
ERXNDL,
ERXNDH,

LO8(RXSTART_INIT), //start lo
HI8(RXSTART_INIT), //start hi
LO8(RXSTOP_INIT ), //end lo
HI8(RXSTOP_INIT ), //end hi

MACON2, 0x00,

MACON1, (MACON1_MARXEN | MACON1_RXPAUS | MACON1_TXPAUS),


MACON3, ( MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN),
MAMXFLL, LO8(1518),
MAMXFLH, HI8(1518),
MABBIPG, 0x12, //half duplex
MAIPGL, 0x12,
MAIPGH, 0x0C, //half duplex
MAADR5,
MAADR4,
MAADR3,
MAADR2,
MAADR1,
MAADR0,
};

ENC28J60_MAC0,
ENC28J60_MAC1,
ENC28J60_MAC2,
ENC28J60_MAC3,
ENC28J60_MAC4,
ENC28J60_MAC5

Trong hm ny, ta s cn hm delay_us delay


Code:
void delay_us(unsigned short time_us)
{
unsigned short delay_loops;
register unsigned short i;
delay_loops = (time_us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty)
// one loop takes 5 cpu cycles
for (i=0; i < delay_loops; i++) {};
}
Trong hm delay trn ta cn 1 thng tin l s chu k my ca CPU/micro giy, do ta cn thm cc thng tin ny vo
file cu hnh chung:
M file ntAVRnet.h, thm vo cc define sau:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef NTAVRNET_H
#define NTAVRNET_H
#ifndef F_CPU
#define F_CPU
12000000
// Cho toc do la 12MHz
#endif //F_CPU
#define CYCLES_PER_US ((F_CPU+500000)/1000000)
//So chu ky lenh trong 1 micro giay
#define LO8(x) ((x)&0xFF)
#define HI8(x) (((x)>>8)&0xFF)
#endif //NTAVRNET_H
V y l hm khi ng ENC28J60:
Code:
void enc28j60Init(void)
{
unsigned char i;
unsigned int timeout=0;
Enc28j60Bank = 0xFF;
ENC28J60_CONTROL_DDR |= (1<<ENC28J60_CONTROL_CS);
ENC28J60_CS_HI();
ENC28J60_SPI_PORT |= (1<<ENC28J60_SPI_SCK); //sck = hi
ENC28J60_SPI_DDR |= (1<<ENC28J60_SPI_SS)|(1<<ENC28J60_SPI_MOSI)|(1<<ENC28J60_SPI_SCK);
//SS,MOSI,SCK = OUT
ENC28J60_SPI_DDR &= ~(1<<ENC28J60_SPI_MISO); //MISO = IN
SPCR = (0<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0);
SPSR = (1<<SPI2X);
delay_us(65000);delay_us(65000);delay_us(65000);
enc28j60SPIWrite(ENC28J60_SOFT_RESET,0, ENC28J60_SOFT_RESET);
delay_us(65000);delay_us(65000);delay_us(65000);
while((!(enc28j60Read(ESTAT) & 0x01)) && (timeout<65000)){timeout++;};
if(timeout>=65000){timeout=0;}
NextPacketPtr = RXSTART_INIT;
for(i=0; i<2*22; i+=2){

enc28j60Write(pgm_read_byte(&enc28j60_config[i+0]),pgm_read_byte(&enc28j60_config[i+1]));
}
enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); //=no loopback of transmitted frames
enc28j60SPIWrite(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
enc28j60SPIWrite(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
enc28j60PhyWrite(PHLCON, 0x347A);
}
Cui cng, nh thm phn khai bo tt c cc hm vit trn vo file header (enc28j60.h) iu ny s gip truy xut d
dng cc hm ny t cc module khc.
Bi tip theo s l lp trnh giao thc ethernet.
Bi 4: Lp trnh giao thc ethernet
HOT NG CA TCP/IP
- D liu truyn t ng dng, n mt trong 2 giao thc vn chuyn (TCP hay UDP). Mt gi tin hay n v d liu (PDU)
ca TCP/UDP thng c gi l segment (on d liu).
- on d liu xung lp Internet, giao thc IP cung cp thng tin nh a ch lun l (a ch IP) v ng gi d
liu vo 1 datagram, thng c gi l gi tin IP (IP packet).
- Datagram IP n lp truy cp mng ( y l giao thc ethernet), v c ng gi vo 1 hay nhiu khung d liu
(frame ethernet), sau a xung tng vt l (v d IC ENC28J60) gi i. Khung d liu c chuyn thnh mt
lung cc bit truyn i trn mi trng mng.
pha thu, qu trnh xy ra ngc li, tng vt l s nhn lung bit, khi phc li frame d liu, giao thc ethernet pha
nhn s x l frame d liu ny, tch ra gi tin IP (IP packet) v y ln giao thc IP nu y l gi IP. Cn trong trng
hp bn trong frame ethernet khng phi l 1 gi IP m l 1 gi tin ca giao thc ARP th n s y gi ny sang cho giao
thc ARP x l (xem li hnh minh ha lu d liu gia cc giao thc).
Ti tng giao thc IP, gi IP s c x l, xc nh xem d liu cha bn trong l ca giao thc no (TCP, UDP, hay
ICPM) v chuyn n giao thc tng ng x l tip theo.
Cui cng, giao thc k (TCP, UDP, hay ICMP s x l tip segment d liu nhn c, xc nh xem d liu ny l ca
ng dng no (v d nh HTTP hay DHCP,) v chuyn d liu n ng dng tng ng
Trc ht, ta cn nm r cu trc ca tt c cc gi tin ca mi giao thc c th x l c thng tin cha trong n.
Ta to 1 file header mi l packet.h, file ny s dng cha m t cu trc ca tt c cc gi tin ca cc giao thc s
dng trong project ny:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef PACKET_H
#define PACKET_H
#endif //PACKET_H
Trc ht ta tm hiu cu trc 1 frame ethernet:

Nh vy 1 frame ethernet bt u bng cc byte Preamble dng b v 1 byte Start of Frame xc nh u frame
(phn ny s c ENC28J60 t ng lc b, ta khng cn quan tm). Tip theo l a ch MAC ca host nhn
(destination address), a ch MAC ca host gi (source address), mi a ch MAC ny gm 6 byte. K n l 2 byte

length (cho bit chiu di) hoc type (cho bit d liu cha trong frame l loi d liu ca giao thc lp trn no). K n
l d liu. Cui cng l phn kim tra li (FCS), phn ny cng c ENC28J60 x l, ta khng quan tm.
Nh vy ta cn khai bo cu trc ca header frame ethernet (t phn a ch n 2 byte type) trong file packet.h
Trc ht ta nh ngha 1 struc cho a ch MAC:
Code:
//-------------------------------------------------------------------------------------//Dia chi vat ly hay dia chi MAC (lop Ethernet)
struct ntEthAddr
{
unsigned char addr[6];
};
K n l header ca frame ethernet:
Code:
//-------------------------------------------------------------------------------------//Ethernet header
// Gom 14 byte:
// 06 byte dia chi dich
// 06 byte dia chi nguon
// 02 byte type (cho biet frame ethernet mang ben trong loai du lieu gi)
#define ETH_HEADER_LEN
14
struct ntEthHeader
{
struct ntEthAddr desAddr;
struct ntEthAddr srcAddr;
unsigned int type;
};
Ta cng nh ngha cc gi tr hng qui nh cho trng Type (tham kho ti liu v ethernet bit thm cc gi tr ca
trng ny):
Code:
//
#define ETH_TYPE_ARP 0x0806
#define ETH_TYPE_IP 0x0800
#define ETH_TYPE_IP6 0x86dd
Nhn tin y cng nh ngha lun cu trc ca cc frame ethernet cho VLAN (802.1q) v VLAN Q-inQ (802.1ad), cu
trc ca header MPLS. y l cc giao thc s dng ph bin trn mng MEN (hay MAN-E) ca VNPT. Bn no khng
quan tm n cc giao thc ny c th b qua, ta ch tp trung vo giao thc ethernet thun ty.
Code:
//-------------------------------------------------------------------------------------//Ethernet header 802.1q VLAN Tagging
struct ntEth802_1qHeader
{
struct ntEthAddr desAddr;
struct ntEthAddr srcAddr;
unsigned int type;
unsigned int TPID;
unsigned int PCP_CFI_VID;
};
#define ETH_802_1Q_HEADER_LEN
18
//
#define ETH_802_1Q_TPID
0x8100
#define ETH_802_1Q_PCP_MASK
0xE000
#define ETH_802_1Q_CFI_MASK
0x1000
#define ETH_802_1Q_VID_MASK
0x0FFF
//-------------------------------------------------------------------------------------//Ethernet header 802.1ad Q-in-Q VLAN Tagging
struct ntEth802_1adHeader
{
struct ntEthAddr desAddr;
struct ntEthAddr srcAddr;
unsigned int type;
unsigned int OuterTPID;
unsigned int OuterPCP_CFI_VID;
unsigned int InnerTPID;
unsigned int InnerPCP_CFI_VID;
};
#define ETH_802_1AD_HEADER_LEN
//

22

#define ETH_802_1AD_TPID
0x88a8
#define ETH_802_QINQ_TPID1
0x9100
#define ETH_802_QINQ_TPID2
0x9200
#define ETH_802_QINQ_TPID3
0x9300
//-------------------------------------------------------------------------------------//Cau truc MPLS Header
struct ntMPLSHeader
{
unsigned int
HighLabelValue;
unsigned char
TrafficClass_Stack;
unsigned char
TTL;
};
#define MPLS_HEADER_LEN
4
//
#define MPLS_LOW_LABEL_MASK
0xF0
#define MPLS_TRF_CLS_MASK
0x0E
#define MPLS_STACK_MASK
0x01
//
Vy l xong phn khai bo cu trc frame ethernet. Tip theo l vit cc hm x l giao thc ethernet.
Trong chng giao thc TCP/IP, giao thc ethernet ng vai tr lp truy nhp v truyn dn. Vic gi v nhn d liu lp
ethernet c thc hin da vo a ch vt l hay cn gi l a ch MAC.
Trong mi frame ethernet u cha 2 a ch MAC: mt a ch ca host gi v 1 a ch ca host nhn
khi lp ethernet nhn c 1 frame d liu, trc ht n s kim tra a ch host nhn xem c phi l a ch ca n
khng (tc l gi cho n), nu ng n s nhn frame ny v chuyn n lp IP. Ngoi ra cn c 1 trng hp na lp
ehternet s nhn frame: l nu a ch host nhn l a ch broadcast (tc l gi cho tt c mi my trong mng LAN),
trong trng hp ny frame s c nhn v x l.
Ngoi vic kim tra a ch, trong frame ethernet cn c 1 trng cha m kim tra li gip pht hin nhng li xy ra
trong qu trnh truyn, cc frame b xc nh l c li s b b qua.
Trong mch ca chng ta, vic kim tra li v kim tra a c thc hin t ng bi IC ENC28J60, do ta khng cn
lp trnh cho cc chc nng ny. Mi khi nhn c 1 frame trn ng truyn, ENC28J60 s kim tra li xem c sai st
khng, tip n s i chiu a ch host nhn vi a ch c cu hnh cho n (trong cc thanh ghi a ch MAC:
MAADR0-5). Nu khng c li v a ch l gi cho n, n s to 1 ngt cng (trn chn INT ca ENC28J60) bo cho
VK bit l n va nhn c 1 frame hp l v yu cu VK x l frame ny.
Vy cng vic ca chng ta l vit hm x l cho trng hp ny, cng nh cung cp 1 hm gi i 1 frame d liu ( s
dng khi mun gi d liu i). Bn cnh ta cng cn mt s hm cung cp cc chc nng b sung nh set/get a ch
MAC,
To 1 file source "ethernet.c" vit module ethernet v file header cho n "ethernet.h"
File ethernet.c
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include <avr/io.h>
#include <avr/pgmspace.h>
#include "packet.h"
#include "enc28j60.h"
#include "enc28j60conf.h"
#include "ethernet.h"
File ethernet.h
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef ETHERNET_H
#define ETHERNET_H
#endif //ETHERNET_H
Lp trnh cho giao thc ethernet (tip theo)
Trc ht, ta khai bo 1 buffer trn b nh RAM ca VK lu tr frame d liu m ta cn x l.
Kch thc ca buffer ny s bng kch thc ln nht ca 1 segment d liu m h thng ca ta c th x l (MTU) +
kch thc header TCP + kch thc header UDP + kch thc header ca frame.
Trong :
- Vi giao thc TCP/IP th MTU max l 1460
- Kch thc Header ca TCP l 20 bytes
- Kch thc Header ca IP l 20 bytes ( y xem nh khng c trng Option trong Header IP, cu trc gi IP s c
gii thch chi tit phn lp trnh cho giao thc IP).

- Kch thc Header ca frame Ethernet l 14 byte.


Vy trc ht ta thm cc khai bo kch thc ny vo file ethernet.h
Code:
#ifndef
MTU_SIZE
#define
MTU_SIZE 1460
#endif
#ifndef
IP_HEADER_LEN
#define IP_HEADER_LEN
20
#endif //IP_HEADER_LEN
#ifndef
TCP_HEADER_LEN
#define TCP_HEADER_LEN
20
#endif //TCP_HEADER_LEN
//
#ifndef ETHERNET_BUFFER_SIZE
#define ETHERNET_BUFFER_SIZE
(700+ETH_HEADER_LEN+IP_HEADER_LEN+TCP_HEADER_LEN)
#endif
S d ta thm iu kin (#ifndef #endif) l v thc ra kch thc Header TCP v IP s c nh ngha trong file
packet.h, MTU_SIZE s c nh ngha trong phn config thng tin chung ca chng trnh, do hin nay ta cha vit cc
phn nn tm thi nh ngha trc.
Sau khai bo buffer dnh cho frame ethernet trong file source (ethernet.c):
Code:
unsigned char ethBuffer[ETHERNET_BUFFER_SIZE];
Tip theo ta vit mt s hm cung cp cc chc nng c bn cho lp ethernet:
Code:
//---------------------------------------------------------------------------//Ham khoi tao chip Ethernet
void ethInit(void)
{
enc28j60Init();
ETH_INT_ENABLE;
}
//-------------------------------------------------------------------------------------//Ham goi 1 frame xuong chip ethernet
void ethSendFrame(unsigned int len, unsigned char* packet)
{
enc28j60PacketSend(len, packet);
}
//-------------------------------------------------------------------------------------//Ham doc 1 frame ethernet tu chip ethernet ve buffer tren RAM cua CPU
unsigned int ethGetFrame(unsigned int maxlen, unsigned char* packet)
{
return enc28j60PacketReceive(maxlen, packet);
}
//-------------------------------------------------------------------------------------//Ham doc dia chi MAC hien tai tu chip ethernet, luu vao buffer macaddr[6]
void ethGetMacAddress(unsigned char* macaddr)
{
*macaddr++ = enc28j60Read(MAADR5);
*macaddr++ = enc28j60Read(MAADR4);
*macaddr++ = enc28j60Read(MAADR3);
*macaddr++ = enc28j60Read(MAADR2);
*macaddr++ = enc28j60Read(MAADR1);
*macaddr++ = enc28j60Read(MAADR0);
}
//-------------------------------------------------------------------------------------//Ham set dia chi MAC (dang luu trong buffer macaddr[6] xuong chip ethernet
void ethSetMacAddress(unsigned char* macaddr)
{
enc28j60Write(MAADR5, *macaddr++);
enc28j60Write(MAADR4, *macaddr++);
enc28j60Write(MAADR3, *macaddr++);
enc28j60Write(MAADR2, *macaddr++);
enc28j60Write(MAADR1, *macaddr++);
enc28j60Write(MAADR0, *macaddr++);
}
//-------------------------------------------------------------------------------------//Ham tra lai con tro den buffer ethernet (tren RAM cua CPU)
unsigned char* ethGetBuffer(void)
{

return ethBuffer;
}
Nhc li l truy xut c n cc hm trong module enc28j60.c, n y cc bn nht thit phi thm cc khai bo
hm vit trong enc28j60.c vo file header enc28j60.h. Tc l trong file enc28j60.h phi c cc dng khai bo
ny:
Code:
//---------------------------------------------------------------------------unsigned char enc28j60SPIRead(unsigned char op, unsigned char address);
void enc28j60SPIWrite(unsigned char op, unsigned char address, unsigned char data);
void enc28j60SetBank(unsigned char address);
void enc28j60ReadBuffer(unsigned int len, unsigned char* data);
void enc28j60WriteBuffer(unsigned int len, unsigned char* data);
unsigned char enc28j60Read(unsigned char address);
void enc28j60Write(unsigned char address, unsigned char data);
unsigned int enc28j60PhyRead(unsigned char address);
void enc28j60PhyWrite(unsigned char address, unsigned int data);
void enc28j60PacketSend(unsigned int len, unsigned char* packet);
unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet);
void delay_us(unsigned short time_us);
void enc28j60Init(void);
Tip theo ta vit phn x l khi ENC28J60 nhn c 1 frame d liu hp l.
Nh ni trc , khi ENC28J60 nhn c 1 frame d liu hp l, n s to 1 ngt bo cho VK bit v x l d
liu nhn c ny. Nh vy ta cn vit mt ISR ngt tng ng cho s kin :
Code:
//-------------------------------------------------------------------------------------//Vector ngat cua ethernet, mot ngat ngoai se duoc khoi tao boi chip ethernet
// moi khi no nhan duoc 1 frame ethernet (dung dia chi cua no)
ISR (ETH_INTERRUPT)
{
eth_got_frame = 1;
time_watchdog = 0;
ETH_INT_DISABLE;
}
Trong hm ny ta c s dng nh ngha vector ngt (ISR), do ta cn include file tng ng vo. Thm dng ny vo
u file "ehternet.c"
Code:
#include <avr/interrupt.h>
Trong hm ny, ta s dng 2 bin ton cc l eth_got_frame v time_watchdog, hai bin ny cn c khai bo trong file
enc28j60.c (nn du file)
Code:
unsigned char eth_got_frame = 0;
volatile unsigned int time_watchdog;
Gii thch: thay v vit ton b phn x l trong hm ngt (ISR), trong hm ngt ta ch n gin l set bin
eth_got_frame = 1 bo cho bit c 1 frame ang ch x l, bin ny (eth_got_frame) s lin tc c kim tra bi
hm dch v ethernet (ethService) m ta s vit sau y, hm ny (ethService) s lin tc c gi trong 1 vng lp
chng trnh chnh (hm main trong file ntAVRnet.c) thc thi lin tc.
Cch vit ny nhm trnh xy ra hin tng ngt chng ngt, c th dn n chng trnh thc thi khng ng mong
mun do ni dung hm ngt qu di, cha thc thi xong xy ra 1 ngt khc.
Cn bin time_watchdog l mt bin nhm pht hin cc li dn n treo cc giao thc mng hoc IC ENC28J60. Bin
ny s c tng lin tc bi timer nhng li c reset v 0 mi khi nhn c 1 frame ethernet mi, iu ny cho php
pht hin 1 khong thi gian qu lu m ta khng nhn c frame ethernet no (khi bin time_watchdog tng n mt
gi tr ngng), khi ta gi thit l ENC28J60 b treo hay pht sinh li, lc ta s gi hm reset IC ny v khi ng
li giao thc ethernet. iu ny trong thc t rt hu ch, n gip mch ca chng ta chy n nh hn rt nhiu.
ng thi ta cng disable ngt ngoi ny trong thi gian ch x l frame.
Vy ta vit tip phn x l frame ethernet trong hm ethService nh sau:
Code:
//-------------------------------------------------------------------------------------//Ham duoc goi lien tuc de thuc thi cac tac vu cua giao thuc ethernet
void ethService(void)
{
int len;
struct ntEthHeader* ethPacket;

if(!eth_got_frame) return;
eth_got_frame = 0;
// look for a packet
len = ethGetFrame(ETHERNET_BUFFER_SIZE, ethBuffer);
if(len)
{
ethPacket = (struct ntEthHeader*)&ethBuffer[0];
#ifdef ETH_DEBUG
printf("Received packet len: %d, type:", len);
#endif
if(ethPacket->type == HTONS(ETH_TYPE_IP))
//Neu day la frame danh cho giao thuc IP
{
#ifdef ETH_DEBUG
printf("IP packet\r\n");
#endif
arpIPPacketIn((unsigned char*)&ethBuffer[0]);
IPProcess( len-ETH_HEADER_LEN, (struct ntIPHeader*)&ethBuffer[ETH_HEADER_LEN]
);
}
else if(ethPacket->type == HTONS(ETH_TYPE_ARP))
//Neu day la 1 frame cua giao thuc ARP
{
#ifdef ETH_DEBUG
printf("ARP packet\r\n");
#endif
arpArpProcess(len, ethBuffer );
}else{
#ifdef ETH_DEBUG
printf("Unknown packet:%x\r\n",ethPacket->type);
#endif
ethInit();
}
ETH_INT_ENABLE;
}
return;
}
//-------------------------------------------------------------------------------------Gii thch:
Hm ny khi pht hin c frame mi (bin eth_got_frame khc 0) th tin hnh kim tra trng Type trong header frame
ethernet xem d liu cha trong frame l ca giao thc no (IP hay ARP) v s gi hm tng ng ca giao thc
x l.
C mt lu quan trng l trong trnh bin dch gcc (cng nh cc trnh bin dch ngn ng C khc cho AVR), i vi cc
bin c kch thc ln hn 1 byte (int, double, long,) th th t cc byte trong b nh ca AVR c sp xp theo th t
ngc li vi th t trong cc header ca gi tin (frame ethernet, IP packet,). Do khi c cc bin ny ra t buffer
ethernet cng nh trc khi ghi vo buffer, ta phi i th t cc byte ny. Ta vit mt s macro cho mc ch ny v lu
lun trong file packet.h s dng sau ny.
Code:
//-------------------------------------------------------------------------------------#define HTONS(s)
((s<<8) | (s>>8))
//danh cho bien 2 byte
#define HTONL(l)
((l<<24) | ((l&0x00FF0000l)>>8) | ((l&0x0000FF00l)<<8) | (l>>24))
//danh
cho bien 4 byte
//
Lu l trong hm ny ta c gi cc hm ca giao thc lp trn (IP v ARP). l cc hm arpIPPacketIn, IPProcess, v
arpArpProcess. Cc hm ny ta vn cha vit nn khi bin dch file ethernet.c s c bo li thiu cc hm ny.
cho mc ch debug sau ny, trong hm ta c s dng hm xut ra cng serial l printf. Hm ny cc bn t vit ly
dng uart nh. Trong ni dung hng dn ny tp trung vo giao thc TCP/IP thi.
Sau khi x l xong frame, ta cn enable ngt ngoi tr li.
n y l c bn xong giao thc ethernet, tip theo s l giao thc IP v ARP, rc ri hn nhiu.
Bi 5: Lp trnh cho giao thc IP (Internet Protocol) v giao thc ARP (Address Rolution Protocol)
Trc ht, ta cn tm hiu v hot ng ca giao thc IP.
(phn ny vit mt cch n gin v d hiu nht cho dn in t, khng chuyn v network c th hiu phn no hot

ng ca cc giao thc c th hiu code v t vit code, dn IT vo c ng ci nh)


Cch thc m d liu c gi qua giao thc IP c tin hnh nh sau:
- Khi nhn c 1 segment d liu (t giao thc lp trn l TCP hay UDP) cn gi n ch no , a ch ch ny phi
c xc nh bng a ch IP (tc l a ch mng hay a ch lun l). Lp giao thc IP s gn thm vo u segment d
liu mt header IP to thnh gi IP hon chnh. Trong header IP ny c cha 2 thng tin quan trng, l a ch host
gi (source IP address) v a ch host nhn (destination IP address). a ch source ng nhin l a ch ca bn thn
n, cn a ch ch phi c cung cp cho lp IP khi mun gi d liu qua giao thc ny.
- Gi tin IP ny sau c chuyn n lp giao thc ethernet thm phn header ethernet vo v gi i.
- Nhng nh phn trc ta bit, giao thc ethernet li gi cc frame d liu i da vo 1 loi a ch khc l a ch
MAC (hay cn gi l a ch vt l). Ti sao li cn n 2 a ch nh vy? L do l a ch vt l ch c gi tr trong phm
vi mng LAN, n s khng th gip xc nh v tr host bn ngoi phm vi mng LAN. Khi gi d liu ra ngoi mng
LAN, cc router s chuyn d liu i da v a ch IP.
- Nh vy trong phn a ch MAC ngun v a ch MAC ch trong header ca frame ehternet, ta s in cc a ch no?
i vi a ch MAC ngun, ng nhin ta s in a ch MAC ca chnh ENC28J60 c xc lp. Nhng cn a ch
MAC ch, s c 2 trng hp xy ra:
+ Nu host ch nm trong cng 1 mng LAN vi chng ta, ta s in a ch MAC ch l a ch tng ng ca host ch.
Frame d liu s c gi thng n ch.
+ Nu host ch nm bn ngoi mng LAN, r rng ta khng th gi d liu trc tip n host ch m phi thng qua
gateway, khi a ch MAC ch phi l a ch gateway. ( d hiu, c hnh dung ta gn mch ny ti nh, sau modem
ADSL cng vi 1 my tnh bn ti nh, nu mch ca chng ta cn gi d liu n my tnh cng ti nh, trong cng
mng LAN, n s gi trc tip theo a ch MAC ca my tnh . Nhng nu cn gi d liu n 1 my tnh bn ngoi,
nm trn mng Internet, khi n khng th gi frame d liu thng n my tnh kia m n phi gi qua gateway,
trong trng hp ny chnh l modem ADSL. Nh vy lc a ch MAC ch phi l a ch MAC ca gateway).
- Vn cn mt vn na m ta phi gii quyt. l trong c hai trng hp trn, d l cn gi cho gateway hay thng
n host ch, th n y, ta mi ch bit a ch IP ca host ch (hay ca gateway) m khng bit a ch MAC tng
ng. Vy ny sinh mt vn l lm sao bit c a ch MAC ca mt host khi bit a ch IP?

n y, chnh l pht sinh vai tr ca giao thc phn gii a ch (APR Address Resolution Protocol). Vai tr ca giao
thc ny l tm ra a ch MAC khi bit a ch IP ca 1 host.
Hot ng ca giao thc ARP:
- Cch thc lm vic ca giao thc ARP thc ra kh n gin. Nhim v ca n l khi giao thc IP hi n: Host c a ch
IP l a.b.c.d th a ch MAC l bao nhiu? th n phi tr li ngay: a ch MAC ca n l XX:XX:XX:XX:XX:XX!. Chc
nng ny trong project ca chng ta s c cung cp bi hm arpIpOut (xem li lu d liu vo ra). Tc l trc
khi giao thc IP chuyn d liu xung cho giao thc ethernet, n s gi hm arpIpOut phn gii a ch MAC cho host
ch.
- Tuy nhin ch chng cha gii thch cho hot ng ca ARP. Cu hi tip theo s l: Vy ARP ly thng tin u
tr li cho cu hi trn?
- Cch thc n gii quyt vn cng n gin khng km: giao thc ARP duy tr mt bng gi l ARP cache gm 2 ct,
mt ct ghi a ch IP, mt ct ghi a ch MAC tng ng vi a ch IP . Mi khi c hi bi giao thc IP, n s tra
bng ny tm cu tr li.
- Vy n y, cc bn phi ny ra ngay 1 cu hi k tip: vy nhng g cha trong bng ARP cache t u m c, khi
mi khi ng h thng, bng ny ng nhin s trng trn. V chuyn g s xy ra khi giao thc ARP c hi v 1 a
ch IP, m khi n tra trong bng ARP th khng thy?
- Cch gii quyt ca giao thc ARP nh sau: khi c hi v mt a ch IP a.b.c.d no m khng c sn trong bng
ARP cache, n s lp tc la ln trong mng LAN: Ai l ngi c a ch IP l a.b.c.d? Cc my tnh trong mng LAN u
nghe c cu hi ny, v l d nhin ch c ng my tnh c a ch IP a.b.c.d s tr li: L ti y, ti c a ch MAC
l XX:XX:XX:XX:XX:XX!. Vy giao thc ARP s lp tc thm cp a ch IP a.b.c.d v a ch MAC XX:XX:XX:XX:XX:XX
vo trong bng ARP cache v tr li li cho giao thc IP: a ch MAC ca n l XX:XX:XX:XX:XX:XX!.

- Nghe c v bun ci nhng trong thc t, trn my tnh ca chng ta, mi vic din ra ng nh vy, vic la ln ca
ARP c thc hin bng cch n gi i mt gi tin c tn gi l ARP request di dng broadcast, tc l gi n mi my
trong mng LAN, a ch MAC ch ca gi broadcast s l FF:FF:FF:FF:FF:FF. Trong gi ARP request c cha a ch IP m
n cn tm. Tt c cc my tnh trong mng LAN s nhn c gi tin ny, v my tnh c a ch IP trn s tr li bng
bn tin ARP reply, trong bn tin ny s c a ch MAC ca n.
- l cch th nht giao thc ARP in thng tin vo bng ARP cache. Cn c 1 cch na kh n gin gip n in
y thng tin vo bng ARP cache: l mi khi c 1 gi tin IP n, l d nhin l pha host gi gi tin ny in y
thng tin a ch MAC (cha trong header ehternet) v a ch IP ca n (cha trong header IP). Nh vy giao thc
ARP s ly cp a ch ny v cp nht vo bng ARP cache.
- iu cui cng cn lu v bng ARP cache ny l cc dng (tc cp a ch IP MAC) cha trong n khng c duy
tr mi mi m c 1 thi gian timeout, qu thi gian ny m khng c thng tin cp nht cho cp a ch th n s b
xa khi ARP cache, v nu l giao thc IP cn gi d liu cho a ch IP b xa th ARP s i hi li v a ch IP .
Note: xem c bng arp cache trn my tnh ca mnh, cc bn c th m ca s command (vo Start->Run->g
cmd, nhn Enter), sau g lnh "arp -a".
By gi ta bt tay vo vit code:
Vic trc tin phi lm l khai bo cu trc header IP v cu trc gi ARP trong file packet.h.
Cu trc ca gi IP nh sau:

- ngha cc field trong header IP:


+ Version (c chiu di 4 bit): cho bit phin bn ca giao thc, i vi trng hp ca chng ta, giao thc l IP version
4, trng ny s lun c gi tr l 4 (0100)
+ Header Length (4 bit): cho bit chiu di ca header IP, tnh theo n v 4 byte (32 bit)
+ TOS (8 bit): Type of Service
+ Total Length (16 bit): 16 bit tng chiu di ca gi IP gm c phn header
+ Identification (16 bit): dng nhn din cc phn on ca gi IP
+ Flags: gm 3 bit
. Bit u tin: khng s dng
. Bit 2: DF (Dont Fragment) = 1 c ngha l khng phn on gi ny
. Bit 3: MF (More Fragment) = 0 => y l phn on cui cng
+ Fragmented offset (13 bit): di (n v 8 byte) tnh t im bt u ca Header ti im bt u ca phn on
(3 trng trn: Identification, Flags, Fragmented offset dng cho trng hp c bit khi ta cn chia on d liu ban u
thnh nhiu phn on, ng gi trong cc gi tin nh hn, khi ta cn dng cc trng ny cho mc ch rp li cc
phn on khi phc li on d liu ban u, trong project ca chng ta s khng c x l trng hp ny).
+ TTL (Time to Live) (8 bit): thi gian tn ti trn mng hoc s chng trn mng m gi i qua trc khi b hy b
+ Protocol (8 bit): nhn din Protocol trn lp IP
+ Header checksum (16 bit): sa sai cho phn Header
+ Cc vng a ch ngun, a ch ch: a ch IP 32 bit
+ Option: cc ty chn dng cho vic kim tra: Loose source routing, Strict source routing, Record route v Timestamp
+ Padding: Gm cc s zero c thm vo sao cho chiu di ca vng Header l bi s ca 32 bit
(Trong phm vi project ca chng ta, s khng c phn option v padding)
Vy ta khai bo trong file packet.h ni dung nh sau:

Code:
//-------------------------------------------------------------------------------------//Cau truc IP header
struct ntIPHeader
{
unsigned char
verHdrLen;
unsigned char
ToS;
unsigned int
Len;
unsigned int
IDNumber;
unsigned int
Offset;
unsigned char
TTL;
unsigned char
Protocol;
unsigned int
Checksum;
unsigned long
srcIPAddr;
unsigned long
desIPAddr;
unsigned char
Option[4];
};
#define IP_HEADER_LEN
20
#define IP_PROTO_ICMP
#define IP_PROTO_TCP
#define IP_PROTO_UDP

1
6
17

Cn y l cu trc gi ARP:

- ngha cc trng:
+ Hardware type (2 bytes): cho bit loi a ch phn cng, i vi a ch MAC ca giao thc ethernet th gi tr ny c
qui nh l "0x0001".
+ Protocol type (2 bytes): cho bit loi a ch giao thc lp trn, i vi a ch IP, gi tr ny c qui nh l 0x0800.
+ HLEN (1 byte): cho bit chiu di ca a ch vt l (a ch MAC).
+ PLEN (1 byte): cho bit chiu di ca a ch giao thc (a ch IP)
+ Operation (2 bytes): cho bit hot ng ang thc hin trong gi tin ny (request hay reply).
+ Sender H/W (hardware address, 6 bytes): a ch vt l ca pha gi.
+ Sender IP (4 bytes): a ch IP ca pha gi.
+ Target H/W (6 bytes): a ch vt l ca pha nhn, nu cha bit th s l cha ton 0.
+ Target IP (4 bytes): a ch IP ca pha nhn.
Vy ta khai bo cu trc gi ARP trong file packet.h nh sau:
Code:
//-------------------------------------------------------------------------------------//Cau truc ARP header
struct ntARPHeader
{
unsigned int
hwType;
unsigned int
protocol;
unsigned char
hwLen;
unsigned char
protoLen;
unsigned int
opcode;
struct ntEthAddr shwaddr;
unsigned long
sipaddr;
struct ntEthAddr dhwaddr;
unsigned long
dipaddr;
};

#define ARP_OPCODE_REQUEST
#define ARP_OPCODE_REPLY 2
#define ARP_HWTYPE_ETH

1
1

Khng c thi gian vit chi tit hn. Bn no c thy ch no kh hiu th c hi nh.
Cho em.
D l trn PIC hay AVR hay bt c micro controller no th c ch cng nh nhau thi (thm ch trn my tnh th cng
tng t), ch khc l i vi PIC thMicrochip cung cp y b th vin cho cc giao thc ethernet, ip, arp, udp,
tcp, dhcp, http, khng cn phi vit li nh anh ang lm cho AVR. C ch nh sau:
- Khi ta m my tnh ln, m trnh duyt v g vo a ch ca webserver (PIC hay AVR g cng th), gi s y ta g
vo a ch IP nh sau:http://192.168.1.10
- Sau khi nhn enter th my tnh ca chng ta s gi i mt bn tin request ca giao thc HTTP (Hyper Text Transfer
Protocol, giao thc truyn/nhn ni dung trang web), thng l HTTP Get thng qua giao thc TCP (vi cng TCP c
qui nh cho giao thc HTTP l 80) n a ch webserver trn.
- Webserver, y chnh l vi iu khin ca chng ta (PIC hay AVR) nhn c bn tin ny (tt nhin bn tin ny s i
qua ht cc lp giao thc ethernet, IP, TCP ri mi n HTTP). Ti y vi iu khin s c v phn tch bn tin HTTP
request ny bit my tnh ang yu cu ti ni dung trang web no.
- Sau vi iu khin s ly ni dung trang web ny (c son tho theo ngn ng HTML) cha trn trn flash ROM, n
cng c th thm vo trang web mt s thng tin (v d c gi tr t cc sensor cm bin nhit v a vo trong
trang web), v gi ton b ni dung trang web thng qua giao thc TCP tr li cho my tnh. Nu ni dung trang web ln
n c th c gi i trn rt nhiu gi tin, v mi gi tin ch cha ti a 1460 byte d liu m thi.
- My tnh nhn ni dung trang web v trnh duyt s hin th ln cho chng ta thy.
- iu khin board t xa qua web, trn trang web ta c th thit k mt nt nhn chng hn. Khi ta nhn nt ny trn
trnh duyt, my tnh s gi i mt bn tin HTTP na l HTTP Post, trong bn tin ny s cha cc thng tin v trng thi
cc nt option hay cc gi tr trong cc edit text c trn trang web.
- Vi iu khin s nhn bn tin HTTP post ny, phn tch d liu cha trong c p ng tng ng (bt
tt relay chng hn) sau n s gi tr li ln na ni dung trang web cp nht nhng thay i va ri (v d bt
reley th trn web s c 1 hnh trn i sang mu chng hn). Trnh duyt s update ni dung ny ln v ta s thy
c tc ng ca thao tc iu khin .
T t anh s vit v gii thch tt c cc hot ng trn AVR, trn PIC cng th nhng cc hm c Microchip cung
cp sn m thi.
Nguyn vn bi dinh_dong
Thy cho em hi ch ny, v va c em va tng tng thc th cho d hiu.
Trong mi frame ethernet u cha 2 a ch MAC: mt a ch ca host gi v 1 a ch ca host nhn
.
Cu hi:S host truyn nhn trong trng hp ny l bao nhiu : 2 hay >2 host ? V em ngh 2 host l TH ring, 1 host truyn 1 host nhn,
th host nhn check IP l chnh n.
N u host nhn c frame m n kim tra ko phi IP add(dst) ca n th n s x l nh th no, c phi lc ny IP add(dst) l IP
broadcast?
V sau ti mt host no , check IP add l ca chnh n th TH1 c xy ra, phi ko ?

Em lin tng TCP/IP lc ny x l IP nh mt Router check IP cho c 1 mng LAN, ...kt ni vi n.


N u frame c gi cho tt c my tnh trong LAN, th s ko c host ch c th n o ?
N u vi HTTP, hay 1 ng dng no khc th iu ny c th c, nhng vi cc ng Email chng hn, cn tnh bo mt ring t th
IPbroadcast li ko c- do cc my u nhn c frame x l.
EM c vi cu, ko bit ng sai th no?
Cu hi ca em thc ra rt hay, vn ny ti khng gii thch chi tit trong phn giao thc ethernet.
- Giao thc ethernet ch h tr 2 hnh thc truyn: unicast: tc l 1 host gi, 1 host nhn; v broadcast, tc l 1 host gi,
tt c cc host trong mng LAN u nhn.
- Trong mng LAN c bn, s dng 1 HUB kt ni cc my tnh vi nhau trong mng LAN. Khi mt my tnh gi i mt
frame ethernet, bt k l n gi unicast hay broadcast, th tt c cc my tnh trong mng LAN (kt ni vi HUB) u
nhn c frame . Nhng mi my tnh s i chiu a ch MAC nhn vi a ch ca chnh n ( y ch kim tra a
ch MAC, khng kim tra a ch IP, khi ln giao thc IP th mi kim tra a ch IP), v cc host s ch nhn frame v
chuyn ln giao thc IP trong 2 trng hp:
+ Hoc a ch l ca chnh n
+ Hoc a ch l broadcast
- Vy iu g s xy ra nu mt my tnh no ph v lut chi, nhn d liu khng phi dnh cho n, nh vy phi
chng n c th nghe trm d liu gi cho my tnh khc.
- Cu tr li y l: ng nh vy, mng LAN kiu ny hon ton khng c bo mt, vi cc phn mm nghe trm d

liu, mt my tnh c th nghe trm d liu ca cc my khc trong cng mng LAN.
- y thit b HUB dng kt ni cc my tnh to thnh mng LAN ch n gin l khi nhn c d liu n 1 port
ca n, n s khuych i v pht ra li tt c cc port, tt c my tnh ni n n u nhn c d liu.
[Flash]http://www.shareswf.com/media/games/swf/16193.swf[/Flash]
[flash=300,200]http://www.shareswf.com/media/games/swf/16193.swf[/flash]
[FLASH=300,300]http://www.shareswf.com/media/games/swf/16193.swf[/FLASH]
- Tt nhin ngi ta cng nhn ra hn ch ca HUB, cng nh mt s hn ch khc, v pht trin mt thit b "thng
minh" hn HUB, l SWITCH.
- V hnh thc, SWITCH cng c nhiu port v dng kt ni cc my tnh to thnh mng LAN ging HUB, tuy nhin s
khc bit l: mi khi nhn c d liu n 1 port ca n, SWITCH s kim tra a ch MAC ch trn frame, sau n tm
xem my tnh c a ch MAC tng ng ang nm port no ca n, v chuyn d liu n port . Nh vy ch c my
tnh nhn c d liu m thi.
[FLASH]http://www.swfcabin.com/open/1320370008[/FLASH]
Hin nay hu ht cc mng LAN l dng SWITCH, tr cc thit b c s port t (<=5 port) l cn dng HUB.
Vic gi broadcast trn mng LAN ch dng cho mt s trng hp c bit, v d nh cho giao thc ARP, hay khi giao
thc IP yu cu gi broadcast (giao thc IP th c 3 hnh thc gi l unicast, multicast v broadcast). a ch MAC
broadcast c qui nh l FF:FF:FF:FF:FF:FF.
Mc nh, vic gi broadcast ra ngoi phm vi mng LAN l khng c php, cc router s chn cc bn tin broadcast v
khng cho n ra khi phm vi mng LAN.
Nguyn vn bi dinh_dong
Cu hi:ARP: Em ngh ti 1 ci l: mnh ko nh 192.xxx.x.x na m c th nh ch no nh avrnet v Enter th c hin th c
webserver khng ? V vai tr ca ARP trong trng hp ny th no.
Li mt cu hi rt ng bn lun na, tuy nhin vn ny khng thuc giao thc ARP m thuc mt h thng khc,
ta gi l h thng tn min (domain name system).
ng ra, my tnh ch gi v nhn d liu trn mng da vo a ch IP. Tc l l ra truy cp vo trang ch yahoo
chng hn, ta phi g a ch IP server ca yahoo: http://98.137.149.56 (cc bn c th th).
Tuy nhin r rng l cch ny qu kh nh vi ngi s dng, do ngi ta mi ngh ra mt loi a ch gi nh d nh
hn, l tn min (domain name) nh vy thay v g: http://98.137.149.56 ta c th g: http://www.yahoo.com.
Nhng vn li pht sinh l my tnh th khng hiu tn min, i vi n th nht thit phi c a ch IP th mi gi
nhn d liu trn mng c.
V vy ngi ta duy tr trn mng Internet mt h thng server gi l Domain Name System Server, vit tt l DNS server
(nu chng ta vo phn cu hnh a ch IP tnh cho my tnh s thy phn ny). Nhim v ca cc server ny l khi c 1
my tnh bt k hi n v mt tn min, n s tr li ngay tn min ng vi a ch IP no.
Vy by gi, nu chng ta m trnh duyt v g vo http://www.yahoo.com th c ch s nh sau:
- My tnh s gi i mt cu hi n DNS server l: tn min http://www.yahoo.com th tng ng vi a ch IP no?
- DNS server s tr li: Tn min www.yahoo.com tng ng vi a ch IP 98.137.149.56.
- My tnh s truy cp theo a ch 98.137.149.56 v ti ni dung trang web yahoo v.
Vy c th s dng tn min, my tnh bt buc phi bit t nht mt a ch DNS server. Thng tin v DNS server s
c cung cp thng qua giao thc DHCP hoc cu hnh tnh.
C rt nhiu DNS server trn mng, mi nh cung cp dch v Internet ca Vit Nam chng hn u c 1 vi DNS server.
V d VNPT c cc DNS server: 203.162.4.190; 203.162.4.191; 203.162.4.1. Viettel c 203.113.131.1; 203.113.131.2;
FPT c 210.245.0.11,...
Vy lm cch no c c tn min ca ring mnh (v d www.avrnet.vn)? Cu tr li l phi ng k tn min (tr
ph) v tr chi ph hng nm duy tr tn min. Lc ta c quyn ch nh tn min tng ng vi a ch IP no.
Nu khng c iu kin mua tn min, ta c th s dng 1 s tn min min ph (v d ca dyndns). l cch m ta s
dng cho project ny (n phn cui cng nh).
qun mt, cn 1 cch na, n gin hn, nhng ch lm c trn tng my tnh thi. l trn mi my tnh c lu
tr 1 file cha tn host v a ch IP tng ng. File ny c tn l hosts, v nm ng dn
"c:\windows\system32\drivers\etc\hosts". Ta c th m file ny v thm vo 1 dng: v d "96.17.180.162
www.avrnet.vn". Lc my tnh s hiu tn th tng ng vi a ch IP nh vy. Nhng cch ny ch c tc dng
trn my tnh m ta sa file hosts thi.
Nguyn vn bi dinh_dong
Thy c th so snh Add lun l v Add MAC c khng ?
T i sao trng MAC ch khi truyn ra internet li l a ch Gateway? gateway ging MAC im no, m li c in vo MAC ch?
V ARP cache c ging vi bng NAT ip khng ? Em thy na l. C phi Gateway and local IP(mng LAN) ca host s cho a ch MAC ca
host ch khng ?
Mong th y tr li!

hiu v 2 loi a ch ta c th hnh dung nh th ny:


Gi s ta cn gi 1 bc th loanh quanh trong xm, ta ch cn ghi tn ngi nhn l c, trong xm s d dng xc nh
ng Nguyn Vn A ch no.
Tuy nhin khi gi th i trong phm vi c nc, nu ta ch ghi tn ngi nhn, thm ch c thm c ngy thng nm sinh
v s chng minh th bo m khng s b trng, th bu in cng b tay v khng bit ng Nguyn Vn A u, v
vi a ch ny (gm tn, ngy thng nm sinh, s chng minh th) th d khng s trng a ch, th n cng khng th
gip ta xc nh c ng Nguyn Vn A ang tnh, thnh ph, ng no.
Vy ta cn mt cch ghi a ch khc, m nhn vo ta xc nh c ni cn chuyn th ti, v d tnh... huyn....
ng.... s nh.
iu ny hon ton tng t vi a ch IP v a ch MAC: a ch MAC mc d l bo m khng trng nhau, nhng nhn
vo n ta khng th bit host c a ch MAC ang u? M, Vit Nam hay Trung Quc,...? Do a ch MAC ch s
dng c trong mng LAN, ni s lng my tnh l t, cc thit b nh SWITCH c th bit ht cc a ch MAC trong
mng.
gi d liu ra ngoi mng LAN, ta cn 1 loi a ch khc, mt a ch m khi nhn vo ta bit ngay l host tng ng
ang M hay Vit Nam, thm ch nu Vit Nam th thuc mng ca nh cung cp dch v no. a ch tha mn yu
cu ny chnh l a ch IP.
S d nh vy v trong a ch IP, ngi ta chia thnh 2 phn, phn u l a ch mng, cho bit my tnh ang thuc
mng no, phn sau l a ch host, gip phn bit cc my tnh trong mng.
Ta c th d dng nhn thy iu ny: cc my tnh trong cng mng th phn u ca a ch IP l ging nhau.
Nhn vo 1 a ch IP, ta s bit ngay my tnh tng ng ang nc no.
Trong phm vi mng LAN, vic chuyn d liu n ch v mt vt l hon ton ch cn da vo HUB hay SWITCH, tuy
nhin khi gi ra ngoi mng LAN th HUB hay SWITCH s b tay, v s khng bit c a ch MAC ca my tnh bn
ngoi. Lc ny, HUB hay SWITCH s chuyn gi tin n mt thit b khc c kh nng a gi tin ra khi mng LAN,
chnh l Gateway, thit b kt ni gia mng LAN vi bn ngoi. V r rng SWITCH chuyn gi tin n Gateway, th
by gi a ch MAC ch trong frame ethernet phi l a ch MAC ca Gateway.
ARP cache hon ton khc bng NAT IP (NAT-Network Address Translation)
Trong project ny s hng dn n kt ni, ci t modem, ng k tn min, thit k website,... ni chung t A-Z lun.
C l mnh cn dng li gii thch r hn v hot ng ca 2 giao thc IP v ARP mt cht, cng nh cc s dng 2
loi a ch IP v MAC trn mng, trc khi vit code tip, tuy hi di dng 1 cht nhng s gip mi ngi hiu r hn
cch thc lm vic ca TCP/IP, nh vy th s d hiu code hn v c th t vit hay sa i code c d dng.
Ta hy xem xt 1 mng v d nh sau:
- Mng LAN ti nh gm 3 my tnh v 1 board mch ca chng ta kt ni vo ADSL router, t ni vo mng ca nh
cung cp dch v.
- Cc bn cng cn bit l thc ra modem ADSL hay ADSL router m ta dng nh, tht ra bn trong n gm 3 thit b:
mt HUB m rng s lng port, cho php nhiu my tnh c th cng kt ni vo mng; mt Router IP ng vai tr
Gateway, thc hin chc nng nh tuyn gia mng bn trong (LAN) v mng bn ngoi (WAN); v cui cng l 1
modem (Modulation - Demodulation) c th truyn d liu trn ng dy ADSL.

Ta x xem xt 2 v d:
V d A: board mch ca chng ta gi d liu n 1 my tnh trong cng mng LAN, v d l my c a ch 192.168.1.6.
V d B: board mch gi d liu n 1 my tnh nm bn ngoi, v d l my c a ch 203.162.44.164
A-Trng hp gi trong mng LAN
Bc 1: Giao thc IP trong board mch nhn c yu cu gi d liu n a ch IP 192.168.1.6
Bc 2: N i hi giao thc ARP (thng qua hm ArpIpOut) v a ch ny. ARP sau khi tm trong bng ARP cache khng
thy, n s gi 1 bn tin ARP request di hnh thc broadcast n mi my tnh trong mng. My tnh c a ch tng
ng s tr li.

Bc 3: ARP s cp nht bng ARP cache v tr li li cho giao thc IP.


Bc 4: giao thc IP dng thng tin ny in vo frame ethernet v chuyn sang giao th ethernet gi i.

B-Trng hp gi ra ngoi mng LAN


Nu vn lm theo cch c th s xy ra trng hp nh sau:

Nh vy, nu vn lm theo cch c, vic gi d liu s tht bi.


Mi vic phi c tin hnh nh sau:

Vy by gi ta bt u vit code cho cc giao thc ip v arp:


Ta to file ip.c vi ni dung ban u
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include
#include
#include
#include
#include

<avr/io.h>
"packet.h"
"ethernet.h"
"arp.h"
"ip.h"

V file header ip.h


Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef IP_H
#define IP_H
#endif //IP_H
Ta cng to 2 file tng ng cho giao thc ARP:
arp.c
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include <avr/io.h>
#include "packet.h"
#include "ethernet.h"
#include "arp.h"
#include "ip.h"
arp.h
Code:
//----------------------------------------------------------------------------

// Writen by NTTam - PTITHCM


//---------------------------------------------------------------------------#ifndef ARP_H
#define ARP_H
//---------------------------------------------------------------------------#endif //ARP_H
Nh ta thy trn, giao thc IP hot ng, n cn bit mt s thng tin c bn:
- a ch IP ca n.
- Subnet Mask ca n (c thi gian se gii thch Subnet mask sau).
- a ch IP ca Gateway.
- a ch MAC ca n.
Ta s lu cc thng tin ny trong mt bin kiu struct l ipConfig. M file ip.h, khai bo kiu struct ny vo:
Code:
//---------------------------------------------------------------------------#include "packet.h"
struct ipConfig
{
unsigned long ip;
unsigned long netmask;
unsigned long gateway;
struct ntEthAddr ethaddr;

///< IP addressing/configuration structure


///< IP address
///< netmask
///< gateway IP address

};
M tip file ip.c, khai bo bin IpMyConfig c kiu l struct ipConfig
Code:
//-------------------------------------------------------------------------------------struct ipConfig IpMyConfig;
///< Local IP address/config structure
Tip theo ta vit trong file ip.c mt s hm chc nng cho giao thc ny:
u tin l hm tnh trng kim tra li (checksum) trong Header IP. Nu cc bn xem li phn cu trc Header ca
IP s thy n c 1 trng kim tra li cho Header (khng bao gm data). Trng ny gip pha nhn gi IP kim tra li
xem thng tin cha trong Header (rt quan trng) c b sai trong qu trnh truyn hay khng. Nu c sai st, gi tin s
b hy b m khng x l.
Pha pht trc khi gi phi tnh gi tr checksum v ghi n vo trng checksum trong header. Pha thu khi nhn gi tin
s t mnh tnh li check sum 1 cch c lp, sau so snh vi checksum m pha pht tnh (lu trong header) nu
c khc bit th tc l c li xy ra, v gi tin s b hy.
Vy hm ny s c giao thc IP s dng c khi gi v nhn gi tin.
Code:
//-------------------------------------------------------------------------------------//Ham tinh checksum cho goi ip
unsigned int ipChecksum(unsigned char *data, unsigned int len)
{
register unsigned long sum = 0;
for (;;) {
if (len < 2)
break;
sum += *((unsigned int *)data);
data+=2;
len -= 2;
}
if (len)
sum += *(unsigned char *) data;
while ((len = (unsigned int) (sum >> 16)) != 0)
sum = (unsigned int) sum + len;
return (unsigned int) sum ^ 0xFFFF;
}
Ngoi l 1 t: khi lp trnh project ny, vit n phn tnh checksum mnh tnh sai, dn n gi IP khng hp l. Phi
dng phn mm Wireshark bt tng gi tin, kim tra li tng bit v tnh li checksum bng tay sa, mt chng 4 ting
cho ring phn checksum ny.
Tip theo l hm set cc gi tr trong struct ipConfig:
Code:

//-------------------------------------------------------------------------------------//Set cac gia tri cau hinh cho giao thuc ip


void ipSetConfig(unsigned long myIp, unsigned long netmask, unsigned long gatewayIp)
{
/*
// set local addressing
IpMyConfig.ip = myIp;
IpMyConfig.netmask = netmask;
IpMyConfig.gateway = gatewayIp;
ethGetMacAddress(IpMyConfig.ethaddr.addr);
*/
struct ntEthAddr ethaddr;
// set local addressing
IpMyConfig.ip = myIp;
IpMyConfig.netmask = netmask;
IpMyConfig.gateway = gatewayIp;
// set ARP association
ethGetMacAddress(ethaddr.addr);
arpSetAddress(&ethaddr, myIp);
}
Hm tr li bin con tr n struct lu thng tin config cho IP, hm ny nhm gip cc module khc truy xut c ti
bin ipConfig thuc module ip.
Code:
//-------------------------------------------------------------------------------------//Tra lai con tro den struct ipConfig
struct ipConfig* ipGetConfig(void)
{
return &IpMyConfig;
}
Hm in ra a ch MAC (dng trong debug hoc khi config board mch qua cng ni tip bng command line.
Code:
//-------------------------------------------------------------------------------------//In ra dia chi ethernet
void ethPrintAddr(struct ntEthAddr* ethAddr)
{
printf("%x:%x:%x:%x:%x:%x",(ethAddr->addr[0]),(ethAddr->addr[1]),(ethAddr->addr[2]),\
(ethAddr->addr[3]),(ethAddr->addr[4]),(ethAddr->addr[5]));
}
Tng t l hm in ra a ch IP
Code:
//-------------------------------------------------------------------------------------//In ra dia chi IP
void ipPrintAddr(unsigned long ipaddr)
{
printf("%d.%d.%d.%d",
((unsigned char*)&ipaddr)[3],
((unsigned char*)&ipaddr)[2],
((unsigned char*)&ipaddr)[1],
((unsigned char*)&ipaddr)[0]);
}
V hm in ra cc thng s cu hnh IP
Code:
//-------------------------------------------------------------------------------------//In ra cac gia tri cau hinh cho giao thuc IP
void ipPrintConfig(struct ipConfig* config)
{
printf("IP Addr : "); ipPrintAddr(config->ip);
printf("\n\r");
printf("Netmask : "); ipPrintAddr(config->netmask);
printf("\n\r");
printf("Gateway : "); ipPrintAddr(config->gateway);
printf("\n\r");
}
Lu : truy xut c cc hm trong module ethernet.c, chng ta phi thm phn khai bo (declare) cc hm ny
vo file header tng ng ethernet.h nh. T nay vic ny l ng nhin, mnh s khng nhc li na.

Ta c s dng hm printf xut d liu ra cng COM, cc bn t vit nh.


Mt s hm thuc module giao thc ARP, ta vn cha vit, c gi y, nn s to thng bo li thiu hm khi bin
dch.
Trn y l mt s hm cng c cung cp cc chc nng h tr cho giao thc IP. Tip theo s l nhng hm x l chnh
trong giao thc IP, bao gm hm gi v nhn gi tin IP.
Ta vit tip hm thc hin gi 1 gi tin qua giao thc IP:
Code:
//-------------------------------------------------------------------------------------//Ham gui 1 goi IP
void ipSend(unsigned long dstIp, unsigned char protocol, unsigned int len, unsigned char* ipData)
{
struct ntEthHeader* ethHeader;
struct ntIPHeader* ipHeader;
ipHeader = (struct ntIPHeader*)(ipData - IP_HEADER_LEN);
ethHeader = (struct ntEthHeader*)(ipData - IP_HEADER_LEN - ETH_HEADER_LEN);
len += IP_HEADER_LEN;
ipHeader->desIPAddr = HTONL(dstIp);
ipHeader->srcIPAddr = HTONL(IpMyConfig.ip);
ipHeader->Protocol = protocol;
ipHeader->Len = HTONS(len);
ipHeader->verHdrLen = 0x45;
ipHeader->ToS = 0;
ipHeader->IDNumber = 0;
ipHeader->Offset = 0;
ipHeader->TTL = IP_TIME_TO_LIVE;
ipHeader->Checksum = 0;
ipHeader->Checksum = ipChecksum((unsigned char*)ipHeader, IP_HEADER_LEN);
if( (dstIp & IpMyConfig.netmask) == (IpMyConfig.ip & IpMyConfig.netmask) )
{
arpIpOut((unsigned char*)ethHeader,0);

// local

send
}
else
{
arpIpOut((unsigned char*)ethHeader,IpMyConfig.gateway);
}
len += ETH_HEADER_LEN;
#ifdef IP_DEBUG
printf("Sending IP packet\r\nAddr: ");

// gateway send

ipPrintAddr(dstIp);printf("\n\rMAC: ");
ethPrintAddr(&(ethHeader->desAddr));
#endif
ethSendFrame(len, (unsigned char*)ethHeader);
}
Gii thch:
- Khi hm ny c gi, c ngha l giao thc lp trn (TCP hay UDP) chun b sn d liu cn gi i (phn data ca
gi IP) v t ln buffer (ethernet buffer). Vy trong hm ny ta cn in y thng tin to nn Header IP v gi
hm ca giao thc ethernet (ethSendFrame) yu cu giao thc ethernet gi gi tin ny i.
- Nh vy phn u, ta tr 2 bin con tr c kiu l IP Header v Ethernet Header n cc v tr tng ng trn buffer.
Sau ln lt tnh ton v in cc gi tr ca cc trng trong Header IP vo.
- Tip theo ta gi giao thc ARP phn gii a ch. Lc ny s c 2 trng hp: nu a ch mng trong a ch IP ch
ging ca chng ta, tc l host ch nm trong cng mng LAN, ta s yu cu ARP tm a ch MAC ch in vo frame
ethernet v gi i (hm ArpIpOut). Nu khc a ch mng, tc l host ch nm bn ngoi mng LAN, ta s yu cu ARP
tm a ch MAC ca gateway v in vo frame ethernet.
- Sau ta gi hm ca giao thc ethernet gi d liu i.
Trong hm ny, ta c s dng 1 gi tr l TTL (Time To Live) in vo trng TTL trong Header IP (xem li cu trc
Header IP). Gi tr ny cn c nh ngha trc. Ta thm nh ngha ny vo file ip.h:
Code:
#define IP_TIME_TO_LIVE
128
//gia tri Time-To-Live (TTL) mc nh cho header IP
C thi gian s gii thch ngha ca trng TTL sau nh.

V hm x l khi nhn c 1 gi tin IP:

Code:
//-------------------------------------------------------------------------------------//Ham xu ly goi IP, duoc goi boi giao thuc ethernet khi paket type duoc xac dinh la IP
void IPProcess(unsigned int len, struct ntIPHeader* packet)
{
// check IP addressing, stop processing if not for me and not a broadcast
if( (HTONL(packet->desIPAddr) != ipGetConfig()->ip) &&
(HTONL(packet->desIPAddr) != (ipGetConfig()->ip|ipGetConfig()->netmask)) &&
(HTONL(packet->desIPAddr) != 0xFFFFFFFF) )
return;
// handle ICMP packet
if( packet->Protocol == IP_PROTO_ICMP )
{
#ifdef IP_DEBUG
printf("IP->Rx: ICMP/IP packet\r\n");
//icmpPrintHeader((icmpip_hdr*)packet);
#endif
icmpIpIn((struct ntIPHeader*)packet);
}
else if( packet->Protocol == IP_PROTO_UDP )
{
#ifdef IP_DEBUG
printf("IP->Rx: UDP/IP packet\r\n");
//debugPrintHexTable(NetBufferLen-14, &NetBuffer[14]);
#endif
UDPProcess(len, ((struct ntIPHeader*)packet) );
}
else if( packet->Protocol == IP_PROTO_TCP )
{
#ifdef IP_DEBUG
printf("IP->Rx: TCP/IP packet\r\n");
#endif
TCPProcess((unsigned char *)packet,len-((packet->verHdrLen & 0x0F)<<2));
}
else
{
#ifdef IP_DEBUG
printf("IP->Rx: IP packet\r\n");
#endif
}
}
//-------------------------------------------------------------------------------------Gii thch:
- Khi nhn c 1 gi IP, vic u tin giao thc IP cn lm l kim tra li a ch IP xem c phi l gi cho mnh khng:
v ta ch nhn nu ng a ch hoc a ch l IP broadcast (lu y l a ch IP broadcast (255.255.255.255) nh,
khng phi MAC broadcast).
- Mc d trc , giao thc ethernet kim tra a ch MAC ri, nhng giao thc IP vn kim tra li a ch IP.
- Tip theo, ta kim tra trng protocol trong header IP xem giao thc lp trn (trn giao thc IP) no gi gi tin
ny (TCP, UDP, hay ICMP) v gi hm ca giao thc tng ng x l.
Vy l xong giao thc IP.
Tip theo ta vit code cho giao thc ARP.
Trc ht ta cn xc nh mt s gi tr hng dnh cho giao thc ARP. l s dng ti a trong bng ARP cache, thi
gian timeout cho mi cp a ch trong bng ARP cache.
Ta m file arp.h thm vo cc nh ngha ny:
Code:
//-------------------------------------------------------------------------------------#include "packet.h"
//-------------------------------------------------------------------------------------#ifndef ARP_TABLE_SIZE
#define ARP_TABLE_SIZE
8
#endif
#ifndef ARP_CACHE_TIME_TO_LIVE
#define ARP_CACHE_TIME_TO_LIVE
#endif

250

Ta cng khai bo trong arp.h mt bin kiu struct cho mi dng trong bng ARP cache, gm 1 a ch IP v a ch MAC
tng ng vi a ch IP :
Code:
//-------------------------------------------------------------------------------------struct ARPentry
{
unsigned long ipAddr;
///< remote-note IP address
struct ntEthAddr ethAddr; ///< remote-node ethernet (hardware/mac) address
unsigned char time;
///< time to live (in ARP table); this is
decremented by arpTimer()
};
Trong mi entry, cn c thm 1 bin l timeout. Nh ni phn trc, mi entry trong ARP cache khng tn ti mi c
1 thi gian timeout nht nh, bin timeout ny s c gn 1 gi tr ban u mi khi c cp nht, v s t ng gim
theo thi gian (nh s dng ngt timer). Nu 1 entry qu lu m khng c cp nht (bin timeout gim v 0) th n s
b xa i (thc ra ta khng cn xa m ch cn xem cc entry c bin timeout = 0 l entry trng).
Ta quay li file arp.c, khai bo mt ARPentry lu cp a ch IP a ch MAC ca chnh board mch v mt array ca
ARPentry lm bng ARP cache:
Code:
//-------------------------------------------------------------------------------------struct ARPentry ARPMyAddr;
struct ARPentry ARPTable[ARP_TABLE_SIZE];
Tip theo ta vit cc hm cho giao thc ARP:
u tin l hm khi to giao thc ARP (thc cht l khi ng gi tr cc bin trong ARP cache m thi):
Code:
//-------------------------------------------------------------------------------------void arpInit(void)
{
unsigned char i;
for(i=0; i<ARP_TABLE_SIZE; i++)
{
ARPTable[i].ipAddr = 0;
ARPTable[i].time = 0;
}
}
Hm set a ch, thc ra ch l khai bo a ch MAC v IP ca bn thn cho ARP:
Code:
//-------------------------------------------------------------------------------------void arpSetAddress(struct ntEthAddr* ethAddr, unsigned long ipAddr)
{
ARPMyAddr.ethAddr = *ethAddr;
ARPMyAddr.ipAddr = ipAddr;
}
Hm tm kim 1 a ch IP trong bng ARP cache, tr li v tr ca entry tng ng vi a ch IP trong bng ARP cache:
Code:
//-------------------------------------------------------------------------------------unsigned char arpSearchIP(unsigned long ipaddr)
{
unsigned char i;
for(i=0; i<ARP_TABLE_SIZE; i++)
{
if((ARPTable[i].ipAddr == ipaddr) && (ARPTable[i].time != 0))
{
return i;
}
}
return -1;
}
Hm cp nht 1 entry trong bng ARP
Code:
//-------------------------------------------------------------------------------------void arpUpdateEntry(struct ntEthAddr ethAddr,unsigned long ipAddr)
{
unsigned char index;

index = arpSearchIP(ipAddr);
if(index < ARP_TABLE_SIZE)
{
ARPTable[index].ethAddr = ethAddr;
ARPTable[index].time = ARP_CACHE_TIME_TO_LIVE;
#ifdef ARP_DEBUG
printf("Update ARP TTL %d: ",index);ipPrintAddr(ipAddr);
printf("-");ethPrintAddr(&ethAddr);printf("\n\r");
#endif
return;
}
for(index=0; index<ARP_TABLE_SIZE; index++)
{
if(!ARPTable[index].time)
{
ARPTable[index].ethAddr = ethAddr;
ARPTable[index].ipAddr = ipAddr;
ARPTable[index].time = ARP_CACHE_TIME_TO_LIVE;
#ifdef ARP_DEBUG
printf("Update ARP: ");ipPrintAddr(ipAddr);
printf("-");ethPrintAddr(&ethAddr);printf("\n\r");
#endif
return;
}
}
}
Hm x l khi nhn c 1 bn tin ARP (do lp giao thc ethernet chuyn n):
Code:
//-------------------------------------------------------------------------------------void arpArpProcess(unsigned int len, unsigned char* ethFrame)
{
struct ntEthHeader* ethHeader;
struct ntARPHeader* arpHeader;
ethHeader = (struct ntEthHeader*)ethFrame;
arpHeader = (struct ntARPHeader*)(ethFrame + ETH_HEADER_LEN);
#ifdef ARP_DEBUG
printf("Received ARP Request\r\n");
arpPrintHeader(arpHeader);
#endif
if(

(arpHeader->hwType == 0x0100) &&


(arpHeader->protocol == 0x0008) &&
(arpHeader->hwLen == 0x06) &&
(arpHeader->protoLen == 0x04) &&
(arpHeader->dipaddr == HTONL(ARPMyAddr.ipAddr))){
if(arpHeader->opcode == HTONS(ARP_OPCODE_REQUEST)){
arpUpdateEntry(arpHeader->shwaddr,HTONL(arpHeader->sipaddr));
arpHeader->dhwaddr = arpHeader->shwaddr;
arpHeader->dipaddr = arpHeader->sipaddr;
arpHeader->shwaddr = ARPMyAddr.ethAddr;
arpHeader->sipaddr = HTONL(ARPMyAddr.ipAddr);
arpHeader->opcode = HTONS(ARP_OPCODE_REPLY);
ethHeader->desAddr = ethHeader->srcAddr;
ethHeader->srcAddr = ARPMyAddr.ethAddr;
#ifdef ARP_DEBUG
printf("Sending ARP Reply\r\n");
arpPrintHeader(arpHeader);
#endif
ethSendFrame(len, (unsigned char*)ethHeader);
return;
}
if(arpHeader->opcode == HTONS(ARP_OPCODE_REPLY)){
arpUpdateEntry(arpHeader->shwaddr,HTONL(arpHeader->sipaddr));
#ifdef ARP_DEBUG
printf("is ARP reply\r\n");
#endif
return;
}

}
#ifdef ARP_DEBUG
printf("Unknown ARP packet\r\n");
#endif

}
hm x l khi nhn c 1 gi IP: nh ni trc y trong ni dung v ARP, c 2 cch cp nht ARP l thng qua
ARP request v thng qua cc gi IP n. Mi khi c 1 gi IP n, l d nhin l gi ny s c giao thc IP x l, ARP
khng can thip vo qu trnh x l . Tuy nhin trong mi gi IP n c 2 thng tin quan trng m ARP cn: l a
ch IP v a ch MAC ca host gi gi tin . ARP s dng cp a ch ny cp nht ARP cache.
Code:
//-------------------------------------------------------------------------------------void arpIPPacketIn(unsigned char* ethFrame)
{
struct ntEthHeader* ethHeader;
struct ntIPHeader* ipHeader;
ethHeader = (struct ntEthHeader*)ethFrame;
ipHeader = (struct ntIPHeader*)(ethFrame + ETH_HEADER_LEN);
arpUpdateEntry(ethHeader->srcAddr,HTONL(ipHeader->srcIPAddr));
}
//-------------------------------------------------------------------------------------Cui cng l hm phn gii a ch cung cp a ch MAC cho giao thc IP khi c yu cu
Code:
void arpIpOut(unsigned char* ethFrame, unsigned long phyDstIp)
{
unsigned char index;
struct ntEthHeader* ethHeader;
struct ntIPHeader* ipHeader;
ethHeader = (struct ntEthHeader*)ethFrame;
ipHeader = (struct ntIPHeader*)(ethFrame + ETH_HEADER_LEN);
if(phyDstIp)
index = arpSearchIP(phyDstIp);
else
index = arpSearchIP(HTONL(ipHeader->desIPAddr));
if(index < ARP_TABLE_SIZE)
{
ethHeader->srcAddr = ARPMyAddr.ethAddr;
ethHeader->desAddr = ARPTable[index].ethAddr;
ethHeader->type = HTONS(ETH_TYPE_IP);
}
else
{
ethHeader->srcAddr = ARPMyAddr.ethAddr;
ethHeader->desAddr.addr[0] = 0xFF;
ethHeader->desAddr.addr[1] = 0xFF;
ethHeader->desAddr.addr[2] = 0xFF;
ethHeader->desAddr.addr[3] = 0xFF;
ethHeader->desAddr.addr[4] = 0xFF;
ethHeader->desAddr.addr[5] = 0xFF;
ethHeader->type = HTONS(ETH_TYPE_IP);
}
#ifdef ARP_DEBUG
printf("ARP Result:");
ipPrintAddr(ARPTable[index].ipAddr);printf("-");
ethPrintAddr(&(ethHeader->desAddr));printf("\r\n");
#endif
}
Trong hm ArpIpOut trn, c 1 ch "lch lut", khng tun th ng nguyn tc lm vic ca ARP, cc bn tm ra, nu
c ai tm ra mnh s gii thch ti sao li lm nh vy.
Hm kim tra timeout ca cc entry trong ARP cache. hm ny s c gi nh k bi ngt timer kim tra xem c
entry no "qu date" hay khng, v hy cc entry .
Code:
//-------------------------------------------------------------------------------------void arpTimer(void)
//Goi moi 10s
{
int index;
for(index=0; index<ARP_TABLE_SIZE; index++)
{
if(ARPTable[index].time)
ARPTable[index].time--;
}

}
//-------------------------------------------------------------------------------------Cc hm phc v cho mc ch debug:
Code:
#ifdef ARP_DEBUG
void arpPrintHeader(struct ntARPHeader* packet)
{
printf("ARP Packet:\r\n");
printf("Operation
: ");
if(packet->opcode == HTONS(ARP_OPCODE_REQUEST))
printf("REQUEST");
else if(packet->opcode == HTONS(ARP_OPCODE_REPLY))
printf("REPLY");
else
printf("UNKNOWN");
printf("\n\r");
printf("SrcHwAddr
: "); ethPrintAddr(&packet->shwaddr);printf("\n\r");
printf("SrcProtoAddr: "); ipPrintAddr(HTONL(packet->sipaddr));printf("\n\r");
printf("DstHwAddr
: "); ethPrintAddr(&packet->dhwaddr);printf("\n\r");
printf("DstProtoAddr: "); ipPrintAddr(HTONL(packet->dipaddr));printf("\n\r");
}
//-------------------------------------------------------------------------------------void arpPrintTable(void)
{
unsigned char i;
// print ARP table
printf("Time
Eth Address
IP Address\r\n");
printf("---------------------------------------\r\n");
for(i=0; i<ARP_TABLE_SIZE; i++)
{
printf("%d",(ARPTable[i].time));
printf("
");
ethPrintAddr(&ARPTable[i].ethAddr);
printf(" ");
ipPrintAddr(ARPTable[i].ipAddr);
printf("\n\r");
}
}
#endif
//-------------------------------------------------------------------------------------Sau khi vit hm xong, nh thm declare vo file header tng ng nh.
n y l xong giao thc IP v ARP, trong phn ny c gi cc hm ca giao thc TCP, UDP v ICMP m ta vn cha
vit ti, nn dch cng s b bo li thiu 3 hm ny nh.
Bi 5: Cc giao thc lp vn chuyn
Vy l xong cc giao thc lp 3, IP v giao thc h tr cho n l ARP. By gi chng ta s chuyn sang cc giao thc
lp 4, lp vn chuyn (Transport Layer). l TCP (Transport Control Protocol) v UDP (User Datagram Protocol), ngoi
ra cn c mt giao thc iu khin cng c th xp vo y, l ICMP (Internet Control Message Protocol).
Trc ht ta ni qua v chc nng v hot ng c bn ca cc giao thc ny trc khi bt tay vo vit code.
Nu ni phn lp trnh giao thc IP phc tp gp i so vi ethernet th c l lp trnh giao thc TCP phi phc tp gp i
c IP v ARP cng li. V trong giao thc TCP, ta phi x l cc vn lin quan n qu trnh bt tay gia hai pha khi
truyn d liu. Phi h tr cng lc nhiu kt ni TCP n cc host khc (v d webserver phi c kh nng x l khi c
ng thi vi ba my tnh cng truy cp vo website), v lin quan cht ch n lp ng dng v dch v. Chnh v vy ta
phi tm hiu k hot ng ca n.
So vi TCP th UDP n gin hn nhiu.
Cn ICMP l mt giao thc dng chuyn qua li cc bn tin iu khin trn mng. V d khi ta g lnh ping trn my
tnh, s c 1 bn tin iu khin l ICMP request c gi n a ch ch. V ni nhn c ICMP request s tr li li
bng bn tin ICMP reply. Nu vit xong giao thc ny th chng ta c th ping n board mch ca chng ta c ri.

C l ta bt u vi giao thc ICMP.


Giao thc thng ip iu khin Internet (Internet Control Message Protocol) c cc router v host trn mng Internet

s dng thng bo v cc vn gp phi trong qu trnh nh tuyn d liu.


Vic ny c thc hin bng cch gi qua li cc bn tin thng bo v cc s kin xy ra trn mng. Cc bn tin ny
c gi l thng ip iu khin Internet (Internet Control Message). C rt nhiu bn tin nh vy, c dng trong
nhng trng hp c th khc nhau. Di y l 1 s bn tin ICMP thng gp:
- Bn tin Echo Request v Echo Reply: s dng cho qu trnh kim tra (lnh ping).
- Bn tin Source Quench: yu cu host ngun gim tc truyn d liu.
- Bn tin Destination Unreachable: thng bo cho host ngun bit datagram khng th chuyn c n ch.
- Bn tin Time Exceeded: thng bo 1 gi tin b hy do TTL = 0.
- Bn tin Fragmentation Needed: thng bo cho host ngun bit 1 datagram c c DF (Dont Fragment) = 1, nhng
router cn phn on datagram ny chuyn n chng k tip.
Trong phm vi project ny, chng ta ch lp trnh cho 2 bn tin l Echo Request v Echo Reply phc v cho vic
ping n board mch ca chng ta.
y l cu trc ca bn tin ICMP:

Bn tin ICMP gm 8 byte:


- Byte u l trng Type: cho bit y l bn tin g.
- Byte th 2 l Code: cho bit m c th cho tng trng hp.
- 2 byte k l checksum: kim tra li.
- 4 byte cn li cha thng tin ring ca tng loi bn tin. Trong trng hp bn tin Echo Request v Echo Reply th
y l s nhn dng (ID) v s tun t ca bn tin.
Vy ta cn khai bo cu trc ca bn tin ICMP vo trong file packet.h:
Code:
//-------------------------------------------------------------------------------------//Cau truc ICMP header
struct ntICMPHeader
{
unsigned char
Type;
unsigned char
Code;
unsigned int
Checksum;
unsigned int
ID;
unsigned int
seqNumber;
};
#define ICMP_HEADER_LEN 8
#define ICMP_TYPE_ECHOREPLY
#define ICMP_TYPE_ECHOREQUEST
8

Tip theo ta to file source v file header cho module giao thc ICMP.
Ni dung ban u ca file icmp.c
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ethernet.h"
#include "arp.h"
#include "ip.h"
#include "icmp.h"
V file icmp.h
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------//======================================================================================
//
icmp.h
//======================================================================================
//
This is header file for icmp.c
//
Writen by NTTam
//
PTITHCM

//
Ver 1.0
//======================================================================================
#ifndef ICMP_H
#define ICMP_H
//-------------------------------------------------------------------------------------#include "packet.h"
//-------------------------------------------------------------------------------------#endif //ICMP_H
By gi ta bt tay vo vit code:
u tin l hm x l khi nhn c bn tin Echo Request (tc l c my tnh ping n board mch.
Code:
//-------------------------------------------------------------------------------------//Ham xu ly goi ICMP nhan duoc
void icmpIpIn(struct ntIPHeader* ipHeader)
{
struct ntICMPHeader* icmpHeader;
icmpHeader = (struct ntICMPHeader*)((unsigned char*)ipHeader + IP_HEADER_LEN);
// check ICMP type
switch(icmpHeader->Type)
{
case ICMP_TYPE_ECHOREQUEST:
// echo request
icmpEchoReply(ipHeader);
break;
default:
break;
}
}
Chc nng hm ny kh n gin: ta kim tra trng Type xem y c ng l bn tin Echo Request hay khng.
Nu ng ta gi hm icmpEchoReply (s vit k tip) tr li.
Tip theo l hm icmpEchoReply gi bn tin Echo Reply tr li cho bn tin Echo Request
Code:
//-------------------------------------------------------------------------------------//Ham gui di ban tin tra loi cho Echo Request (Echo Reply)
void icmpEchoReply(struct ntIPHeader* ipHeader)
{
unsigned long tempIp;
unsigned char* ethFrame;
struct ntICMPHeader* icmpHeader;
icmpHeader = (struct ntICMPHeader*)((unsigned char*)ipHeader + IP_HEADER_LEN);
icmpHeader->Type = ICMP_TYPE_ECHOREPLY;
icmpHeader->Checksum = 0;
icmpHeader->Checksum = ipChecksum((unsigned char*)icmpHeader, HTONS(ipHeader->Len)IP_HEADER_LEN);
tempIp = ipHeader->desIPAddr;
ipHeader->desIPAddr = ipHeader->srcIPAddr;
ipHeader->srcIPAddr = tempIp;
ethFrame = ((unsigned char*)ipHeader);
ethFrame -= ETH_HEADER_LEN;
arpIpOut(ethFrame, 0);
#ifdef ICMP_DEBUG
icmpPrintHeader(ipHeader);
#endif
ethSendFrame(HTONS(ipHeader->Len)+ETH_HEADER_LEN, ethFrame);
}
Ni dung thc hin trong hm ny kh n gin:
- Ta in cc ni dung cn thit cho bn tin Echo Reply.
- Gi giao thc ARP phn gii a ch
- Gi hm ethSendFrame ca giao thc ethernet gi frame ethernet i.
Cui cng l 1 hm dng cho mc ch debug:
Code:
//-------------------------------------------------------------------------------------#ifdef ICMP_DEBUG
//In ra Header cua goi ICPM

void icmpPrintHeader(struct ntIPHeader* ipHeader)


{
struct ntICMPHeader* icmpHeader;
icmpHeader = (struct ntICMPHeader*)((unsigned char*)ipHeader + IP_HEADER_LEN);
printf("ICMP Packet:\r\n");
// print source IP address
printf("SrcIpAddr: ");
ipPrintAddr(HTONL(ipHeader->srcIPAddr)); printf("\n\r");
// print dest IP address
printf("DstIpAddr: ");
ipPrintAddr(HTONL(ipHeader->desIPAddr)); printf("\n\r");
// print type
printf("Type
: ");
switch(icmpHeader->Type)
{
case ICMP_TYPE_ECHOREQUEST:
printf("ECHO REQUEST"); break;
case ICMP_TYPE_ECHOREPLY:
printf("ECHO REPLY"); break;
default:
printf("UNKNOWN"); break;
}
printf("\n\r");
// print code
printf("Code: 0x%x \n\r",(unsigned int)(icmpHeader->Code));
}
#endif
//-------------------------------------------------------------------------------------Ta cng phi nh thm declare cc hm va vit vo file header (icmp.h):
Code:
void icmpIpIn(struct ntIPHeader* ipHeader);
void icmpEchoReply(struct ntIPHeader* ipHeader);
void icmpPrintHeader(struct ntIPHeader* ipHeader);
Vy l xong giao thc ICMP.
n y vn cha ping c nh, v ta vn cha vit ngt timer phc v cho cc hm kim tra thi gian timeout v ni
dung cho chng trnh chnh (main()).

Giao thc TCP (Transport Control Protocol):


Tip theo l giao thc kh chu nht trong chng giao thc TCP/IP. chnh l giao thc TCP (Transport Control Protocol)
Nhim v chnh ca TCP l m bo d liu n ch ng v trn mt mi trng truyn ti khng ng tin cy (IP).
hiu chc nng v cch m TCP thc hin chc nng , ta xem minh ha sau y:

n y c 3 trng hp xy ra:
- TH 1: mi vic sun s, th k bn B nhn c th, gi th tr li bo nhn c thng ip. Th k bn A s hy
bn photo cn lu d, vic gi thng ip thnh cng.
- TH2: bu in lm mt th, bn B khng nhn c. Nh vy th k bn A ch 1 thi gian khng thy phn hi s ly
bn photo ra gi li ln na.
- TH 3: th k bn B nhn c v gi th bo nhn, nhng bu in li lm tht lc th ny. Th k bn A c mt
thi gian khng thy cng s gi li. Khi bn B nhn c thng ip mt ln na cng s gi bo nhn mt ln na.
Cu trc Header TCP:

Ch thch:
- S port ch v s port ngun: phn bit cc tin trnh ng dng ang xy ra trong my tnh
- Cc s sequence v Acknowledgement: s sequence phn bit cc segment khc nhau trong mt dng d liu, cc
s Acknowledgement dng trong c ch xc nhn
- Vng Data offset: chiu di ca Header tnh theo n v 32 bit

- Mt s c (flags):
. URG (Urgent): thit lp 1 khi c d liu quan trng cn truyn ngay.
. ACK: cho bit c s xc nhn nm trong vng Acknowledgement
. PSH (Push): c thit lp trong trng hp d liu nn c giao tc thi
. RST (Reset): ch th mt li sai v hy b phin lm vic
. SYN (Synchronize): trong cc bn tin khi to khi thit lp mt kt ni truyn d liu
. FIN (Finish): dng ng 1 phin lm vic
- Vng Window: ch ra s lng khng gian b m kh dng nhn d liu
- Vng Checksum: vng kim tra sai cho c segment
- Vng Urgent Pointer: ch ra chiu di ca d liu urgent
- Vng Options: xc nh kch thc cc i ca 1 segment
C th hn, vai tr ca TCP trong chng giao thc TCP gm 3 chc nng chnh: iu khin lung, kim sot li v bo
nhn.
- iu khin lung: iu phi tc v kch thc lung d liu m bo pha nhn kh nng nhn v x l lung
d liu.
- Kim sot li: m bo cc gi tin n ng v
- Bo nhn: khi nhn c d liu v khng c li, pha nhn phi bo li vi pha gi bit.
thc hin c cc chc nng , mt qu trnh truyn d liu qua giao thc TCP (m ta gi l phin truyn thng
session) gm c 3 giai on:
- Thit lp kt ni
- Truyn d liu
- Gii ta kt ni

c th hnh dung c qu trnh , mi cc bn xem minh ha sau:


Thit lp kt ni:

Truyn d liu:

Gii ta kt ni:

By gi ta lin h vi cc trng trong TCP Header nh:

c th gim st cht ch trng thi v mi s kin xy ra trong 1 kt ni TCP, trng thi ca mt kt ni TCP c
chuyn i tun theo mt lu trng thi nh sau:

y chnh l thut ton chnh m ta phi lp trnh cho giao thc TCP. Nhn thy s cha

Gii thch:
- TCP l giao thc hng kt ni, dng client server. Tc l trong 1 phin truyn thng th s c mt pha ng vai tr
client (chnh l pha khi to kt ni, trong v d minh ha trn l cng ty A, bn tri), pha cn li, lc no cng trng
thi ch i cc client thit lp kt ni ti chnh l server.
- V d khi ta truy cp web, th my tnh ca ta l client, my ch cha trang web chnh l server, lc no cng trng
thi i cc my tnh client kt ni n (v phi c kh nng thit lp ng thi nhiu kt ni, v c th c nhiu client kt
ni ti cng lc).

- i vi mch m chng ta nh lm, d nhin l thng thng n ng vai tr server ri.


- Trong lu trn, p dng cho c client v server. C client v server u bt u bng trng thi Close. Client s
thit lp kt ni theo con ng Active Open (n ch ng thit lp kt ni). Server s thit lp kt ni theo con ng
Passive Open (th ng, v n i client bt u m)
Qu trnh chuyn trng thi: ta hy xem xt kch bn thng thng nht.
- C hai bt u bng trng thi close, khng c kt ni no tn ti.
- Khi Server m mt port TCP i client thit lp kt ni, n chuyn sang trng thi Listen.
- Khi client gi i bn tin SYN (bc s 1 trong v d minh ha, giai on thit lp kt ni), n chuyn sang trng thi
SYN sent.
- Lc ny khi server nhn c bn tin SYN t client v gi p li 1 bn tin SYN (bc 2 trong VD), n chuyn sang
trng thi SYN Received.
- Lc ny client gi li bn tin xc nhn ACK (bc 3 trong v d), n chuyn sang trng thi thit lp kt ni
Established.
- Server nhn c bn tin ACK trn ca client, n cng chuyn sang trng thi Established.
- Sau 2 bn tin hnh truyn d liu, trng thi c 2 pha u l Established.
- Mt trong hai pha truyn xong d liu, n y th vai tr hai bn l nh nhau, ta gi s client truyn xong d liu
trc, n s gi bn tin FIN, v chuyn sang trng thi FIN wait 1.
- Pha server nhn c bn tin ny, gi xc nhn ACK, v chuyn sang trng thi Close wait.
- Khi client nhn c xc nhn t server (nhn c bn tin ACK trn) th n chuyn sang trng thi FIN wait 2.
- n lc ny server vn c th tip tc gi d liu v client vn tip tc nhn (v ch c client bo l gi xong d liu).
- n khi no server cng gi ht d liu, n s gi i bn tin FIN, cho bit n cng gi xong d liu v chuyn sang
trng thi LAST ACK.
- Khi client nhn c bn tin FIN trn t server, n gi xc nhn (ACK) v chuyn sang trng thi Time wait, sau
ch 1 khong thi gian Timeout v ng kt ni, quay li trng thi Close.
- Khi server nhn c n cng chuyn t Last ACK sang Close (khng cn i Timeout)
thay i khng kh t. Hm trc mnh ni l nu vit xong giao thc ICMP, cha cn TCP v UDP, th c th ping
c ti board mch ca chng ta. T u n gi chng ta vit code qu tri lun m cha th np vo chip chy th
1 ci, k cng hi nn. Vy ti y mnh dng li hng dn b sung mt s hm v vit hm main() trong file
ntAVRnet.c c th bin dch np vo chip Atmega32, sau ta s th ping ti mch xem mch ca ta hot ng
cha nh.
u tin, ta phi vit mt s hm m t u n gi ta vn cha vit: l hm printf s dng uart xut thng tin ln
cng COM trn my tnh v ngt cho timer.
Phn ny s khng gii thch chi tit v khng phi l trng tm chnh, cc bn t tm hiu nh:
Thm vo project cp file uart.c v uart.h
Ni dung file uart.c:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include "ntAVRnet.h"
#include "uart.h"
//---------------------------------------------------------------------------char UartRxBuffer[UART_RX_BUFFER_SIZE];
char UartTxBuffer[UART_TX_BUFFER_SIZE];
volatile unsigned char UartTxBufferStart;
volatile unsigned char UartTxBufferLen;
volatile unsigned char UartRxBufferStart;
volatile unsigned char UartRxBufferLen;
static char HexTable[] PROGMEM= "0123456789ABCDEF";
//---------------------------------------------------------------------------void uartInit(unsigned long baudrate)
{
unsigned int bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);//
UBRRL = bauddiv;
#ifdef UBRRH
UBRRH = ((bauddiv>>8) & 0x0F);
// URSEL
7
// UMSEL
6
0:Asynchronuos/1:Synchronous

// UPM1
5
Parity mode: 00:disabled/01:Reserved/10:Even/11:Odd
// UPM0
4
// USBS
3
Stop bit: 0:1 bit/1:2 bit
// UCSZ1
2
Char size:000:5/001:6/010:7/011:8/111:9/others:reserverd
// UCSZ0
1
// UCPOL
0
UCSRC = 0x80 | (1<<UCSZ1) | (1<<UCSZ0);
#endif
UCR =((1 << TXEN) | (1 << RXEN) | (1<< RXCIE) | (1<< TXCIE));//
UartTxBufferStart = 0;
UartTxBufferLen = 0;
UartRxBufferStart = 0;
UartRxBufferLen = 0;
sei();
}
//-------------------------------------------------------------------------------------SIGNAL(SIG_UART_TRANS)
{
if(UartTxBufferLen){
--UartTxBufferLen;
UDR = UartTxBuffer[UartTxBufferStart++];
if (UartTxBufferStart == UART_TX_BUFFER_SIZE)
UartTxBufferStart = 0;
}
}
//-------------------------------------------------------------------------------------SIGNAL(SIG_UART_RECV)
{
unsigned char i;
char status,data;
status = USR;
data = UDR;
if ((status & ((1<<FE) | (1<<PE) | (1<<DOR))) == 0){
if(++UartRxBufferLen == UART_RX_BUFFER_SIZE)
UartRxBufferLen = UART_RX_BUFFER_SIZE;
i = UartRxBufferStart+UartRxBufferLen;
if(i > UART_RX_BUFFER_SIZE)
i -= UART_RX_BUFFER_SIZE;
UartRxBuffer[i-1] = data;

//Vi tri ky tu cuoi cung trong buffer

}
}
//-------------------------------------------------------------------------------------char uartGetByte(void)
{
//
char c;
if(UartRxBufferLen){
UartRxBufferLen--;
c = UartRxBuffer[UartRxBufferStart++];
if(UartRxBufferStart == UART_RX_BUFFER_SIZE)
UartRxBufferStart = 0;
return(c);
}
return(-1);
}
//-------------------------------------------------------------------------------------void uartSendByte(char c)
{
unsigned char i;
if((USR & (1<<UDRE)) && (UartTxBufferLen == 0)){
//Neu uart dang san sang va buffer trong
UDR = c;
//Gui luon
}else{
//Neu uart dang ban
while(UartTxBufferLen == UART_TX_BUFFER_SIZE);
//Cho neu buffer dang day
i = UartTxBufferStart + UartTxBufferLen;
UartTxBufferLen++;
if(i >= UART_TX_BUFFER_SIZE)
i -=UART_TX_BUFFER_SIZE;
UartTxBuffer[i] = c;
//Ghi vao cuoi buffer
}
}
//-------------------------------------------------------------------------------------int printfP(const prog_char *format, ...)

{
// simple printf routine
// define a global HexChars or use line below
//static char HexChars[16] = "0123456789ABCDEF";
char c;
unsigned int u_val, div_val, base;
va_list ap;
va_start(ap, format);
for (;;)
{
while ((c = pgm_read_byte(format++) ) != '%')
{
// Until '%' or '\0'
if (!c)
{
va_end(ap);
return(0);
}
uartSendByte(c);
}

//

switch (c = pgm_read_byte(format++) )
{
case 'c': c = va_arg(ap,int);
default: uartSendByte(c); continue;
case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
case 'x': base = 16; div_val = 0x10;
case 'x': base = 16; div_val = 0x1000;
CONVERSION_LOOP:
u_val = va_arg(ap,int);
if (c == 'd')
{
if (((int)u_val) < 0)
{
u_val = - u_val;
uartSendByte('-');
}
while (div_val > 1 && div_val > u_val) div_val /= 10;
}
do
{
//c =pgm_read_byte(HexTable+(u_val/div_val));
uartSendByte(pgm_read_byte(HexTable+(u_val/div_val)));
u_val %= div_val;
div_val /= base;
} while (div_val);
}
}
va_end(ap);

}
//-------------------------------------------------------------------------------------Ni dung file uart.h:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef UART_H
#define UART_H
#include <avr/pgmspace.h>
//---------------------------------------------------------------------------#define UART_TX_BUFFER_SIZE
8
#define UART_RX_BUFFER_SIZE
8
//-------------------------------------------------------------------------------------#ifndef UART_INTERRUPT_HANDLER
#define UART_INTERRUPT_HANDLER
SIGNAL
#endif
//define for ATmega32 register
#define USR UCSRA
#define UCR UCSRB

#define UBRR UBRRL


#define EICR EICRB
#define USART_RX USART_RXC_vect
#define USART_TX USART_TXC_vect
//-------------------------------------------------------------------------------------void uartInit(unsigned long baudrate);
char uartGetByte();
void uartSendByte(char c);
int printfP(const prog_char *format, ...);
#define printf(format, args...) printfP(PSTR(format), ## args)
//-------------------------------------------------------------------------------------#endif //UART_H
Tip tc hm vo project cp file timer.c v timer.h
Ni dung file timer.c:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include <avr/io.h>
#include <avr/interrupt.h>
#include "ntAVRnet.h"
#include "timer.h"
#include "ethernet.h"
#include "arp.h"
//#include "tcp.h"
//---------------------------------------------------------------------------extern volatile unsigned int time_watchdog;
static volatile unsigned long UptimeMs;
static volatile unsigned char Counter10ms;
static volatile unsigned int Counter1s;
//---------------------------------------------------------------------------void timer1Init(void)
{
// initialize timer 1
// set prescaler on timer 1
TCCR1B = (TCCR1B & ~TIMER_PRESCALE_MASK) | TIMER1PRESCALE; // set prescaler
TCNT1H = 0;
// reset TCNT1
TCNT1L = 0;
TIMSK |= (1<<TOIE1);
// enable TCNT1 overflow
TCNT1 = 0xFFFF - TIMER1_INTERVAL;
}
void timerInit(void)
{
timer1Init();
sei();
}
//! Interrupt handler for tcnt1 overflow interrupt
TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
{
//Tai nap gia tri timer 1
TCNT1 = 0xFFFF - TIMER1_INTERVAL;
//Cap nhat watchdog timer
if((time_watchdog++) > 120){
time_watchdog = 0;
ethInit();
}
Counter1s++;
arpTimer();
//TCPCheckTimeOut();
}
Ni dung file timer.h:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef TIMER_H
#define TIMER_H
//----------------------------------------------------------------------------

#define
#define
#define
#define
#define
#define
#define
#define
#define

TIMER_CLK_STOP
TIMER_CLK_DIV1
TIMER_CLK_DIV8
TIMER_CLK_DIV64
TIMER_CLK_DIV256
TIMER_CLK_DIV1024
TIMER_CLK_T_FALL
TIMER_CLK_T_RISE
TIMER_PRESCALE_MASK

#define TIMER1PRESCALE
#ifndef TIMER_INTERRUPT_HANDLER
#define TIMER_INTERRUPT_HANDLER
#endif
void timer1Init(void);
void timerInit(void);

0x04
0x05
0x06
0x07

0x00
0x01
0x02
0x03
///<
///<
///<
///<
0x07

///< Timer Stopped


///< Timer clocked at F_CPU
///< Timer clocked at F_CPU/8
///< Timer clocked at F_CPU/64
Timer clocked at F_CPU/256
Timer clocked at F_CPU/1024
Timer clocked at T falling edge
Timer clocked at T rising edge
///< Timer Prescaler Bit-Mask

TIMER_CLK_DIV64

///< timer 1 prescaler default

SIGNAL

#endif //TIMER_H
Mc ch chnh ca timer y l ta to ra ngt ( y dng timer 1, cc bn dng timer no cng c), gi hm
kim tra timeout v cp nht watchdog timer.
Thm define vo ntAVRnet.h
Code:
#define TIMER_PRESCALE
#define TIMER1_INTERVAL

1024
(F_CPU/TIMER_PRESCALE)

#define IPDOT(a,b,c,d)
((unsigned long)((unsigned char)a)<<24)+((unsigned long)((unsigned
char)b)<<16)+((unsigned long)((unsigned char)c)<<8)+(unsigned char)d//((a<<24)|(b<<16)|(c<<8)|(d))
#define IPADDRESS
IPDOT(192,168,1,10)
#define NETMASK
IPDOT(255,255,255,0)
#define GATEWAY
IPDOT(192,168,1,1)
#define
#define
#define
#define
#define
#define

ETHADDR0
ETHADDR1
ETHADDR2
ETHADDR3
ETHADDR4
ETHADDR5

'0'
'F'
'F'
'I'
'C'
'E'

Thm include vo ethernet.c t c th gi cc hm ca giao thc ip v arp:


Code:
#include "arp.h"
#include "ip.h"
Thm include vo file ip.c:
Code:
#include "icmp.h"
#include "uart.h"
V thm thm // vo trc lnh gi hm UDPProcess, TCPProcess trong hm IPProcess (v ta vn cha vit 2 hm ny
ca giao thc UDP v TCP).
M ntAVRnet.c:
Thm hm khi ng cc dch v mng:
Code:
void netInit(unsigned long ipaddress, unsigned long netmask, unsigned long gatewayip)
{
// init network device driver
#ifdef NET_DEBUG
printf("Initializing Network Device\r\n");
#endif
ethInit();
// init ARP
#ifdef NET_DEBUG
printf("Initializing ARP cache\r\n");

#endif
arpInit();
// init addressing
#ifdef NET _DEBUG
printf("Initializing Addressing\r\n");
#endif
ipSetConfig(ipaddress, netmask, gatewayip);
//dhcpInit();
//TCPInit();
//httpInit();
}
Hm xut ra cng serial cc thng tin cu hnh IP:
Code:
//-------------------------------------------------------------------------------------void
PrintIPConfig()
{
printf("MAC Address: ");
ethPrintAddr(&IpMyConfig.ethaddr);
printf("\n\r");
printf("IP Address: ");
ipPrintAddr(IpMyConfig.ip);
printf("\n\r");
printf("Subnet Mask: ");
ipPrintAddr(IpMyConfig.netmask);
printf("\n\r");
printf("Default Gateway: ");
ipPrintAddr(IpMyConfig.gateway);
printf("\n\r");
}
hm ny c th truy xut bin IpMyConfig nm trong module ip.c, ta thm dng khai bo sau vo u file
ntAVRnet.c.
Code:
extern struct ipConfig IpMyConfig;
V vit hm khi ng h thng:
Code:
//-------------------------------------------------------------------------------------void
SystemInit()
{
timerInit();
uartInit(UART_BAUDRATE);
}
V cui cng l vit hm main():
Code:
int
{

main(void)
SystemInit();
printf("\r\nNTTam AVR network testing with enc28j60.\r\n");
printf("Initializing Network Interface and Stack\r\n");
printf("Ethernet chip init\r\n");
IpMyConfig.ethaddr.addr[0] = ETHADDR0;
IpMyConfig.ethaddr.addr[1] = ETHADDR1;
IpMyConfig.ethaddr.addr[2] = ETHADDR2;
IpMyConfig.ethaddr.addr[3] = ETHADDR3;
IpMyConfig.ethaddr.addr[4] = ETHADDR4;
IpMyConfig.ethaddr.addr[5] = ETHADDR5;
IpMyConfig.ip = IPADDRESS;
IpMyConfig.netmask = NETMASK;
IpMyConfig.gateway = GATEWAY;
netInit(IpMyConfig.ip, IpMyConfig.netmask, IpMyConfig.gateway);
PrintIPConfig();
while(1)
{
ethService();
}
return 0;}

Bin dch, np chip v th g lnh ping 192.168.1.10 xem sao.


a ch IP, Subnet v gateway cc bn c th thay i cc define trong file ntAVRnet.h cho ph hp vi mng nh
mnh nh.

Nguyn vn bi rptdnmqs
Thy gii thch dm em ci hm ipchecksum.Em tng check sum l cng tng byte d liu li thi.Sao m li c ci while l th.
Hehe, bi vy, lc vit code ch ny ti cng tng vy, c ngh l mnh bit ri, t ra l cha bit g c (hay ni chnh
xc hn l bit cha ti). Nguyn nhn l th ny:
- ng l checksum l cng li nhng:
1-Cng tng word (16 bit) ch khng phi tng byte
2-Checksum IP c quy nh l: "b-1 16 bit ca tng b-1 ca tt ca cc t 16 bit trong header IP".
Nghe hi kh hiu, c th l th ny:
- u tin ta cng cc t 16 bit trong header:
Code:
for (;;) {
if (len < 2)
break;
sum += *((unsigned int *)data);
data+=2;
len -= 2;
}
Nn nh data l bin con tr n kiu char, v vy ta p kiu n sang bin con tr kiu int: (unsigned int *)data v ly gi
tr ti a ch con tr th c s 16 bit: *((unsigned int *)data). Tip theo ta tng bin con tr thm 2 byte v tr len i 2
byte. Lp n khi no s byte cn li nh hn 2.
n y, nu s byte l chn, len=0, nu s byte l (chia tng cp 2 byte cn tha li 1 byte) th len=1. Ta cng nt byte
vo (xem n nh l 1 t 2 byte m byte cao bng 0x00):
Code:
if (len)//Tuc la len=1, con thua 1 byte
sum += *(unsigned char *) data;
Nh vy l ta tnh tng ca header xong, nhng nn nh khi cng nh vy trong AVR, kt qu s l tng b-2 ch khng
phi tng b-1 nh yu cu.
chuyn tng b-2 sang b-1, ta cn cng phn d vo, chnh v l do ny m ta khai bo bin sum l bin long, c
chiu di 4 byte, hai byte cao ca n cha phn d.
Code:
while ((len = (unsigned int) (sum >> 16)) != 0)
sum = (unsigned int) sum + len;
y ta gn len=(unsigned int) (sum >> 16) chnh l 2 byte cao ca bin 4 byte sum, lc ny bin len c tn dng
nh l 1 bin tm thi, khng c ngha l chiu di na.
Ta em phn d (2 byte cao, c cha trong bin len) cng vi 2 byte thp: (unsigned int) sum (phi p kiu sum t
long sang int nu khng n s cng c 4 byte ca sum).
Vng lp ny cho n khi no 2 byte cao ca sum=0x0000 (ht phn d).
Vy kt qu ta thu c by gi l :"tng b-1 ca tt ca cc t 16 bit trong header IP".
Cui cng ta cn ly b-1 ca kt qu ny, l checksum IP.
Code:
return (unsigned int) sum ^ 0xFFFF;
Phc tp cha. ni l khi vit phn ny ti mt 4h ch sa hm checksum v debug cc gi IP xem mnh sai ch
no. Em thc mc cng khng c g l.
Lc trc ti khng m phng, m ni chung trc gi him khi no m phng trc khi lm mch, v mch phc tp th
vic m phng khng c nhiu ngha, m mch n gin th cn g phi m phng, ch m phng mch analog thi.
ng l ti qun mt define thng s ny, cc bn thm vo, tc ty mi ngi thi. V d:
Code:
#define

UART_BAURATE

9600l

By gi l phn code cho TCP :


Ta li to 2 file source v header :
tcp.c :
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ethernet.h"

#include "ip.h"
#include "uart.h"
#include "tcp.h"
tcp.h :
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef TCP_H
#define TCP_H
#endif //TCP_H
u tin l m file packet.h, thm m t TCP header vo :
Code:
//-------------------------------------------------------------------------------------//Cau truc TCP header
struct ntTCPHeader
{
unsigned int
srcPort;
unsigned int
desPort;
unsigned long
seqNumber;
unsigned long
ackNumber;
unsigned char
Offset;
unsigned char
Flags;
unsigned int
Window;
unsigned int
Checksum;
unsigned int
UrgentPtr;
unsigned char
optdata[8];
};
#define TCP_HEADER_LEN
20
nh ngha cc c (flags) trong header TCP: v khi truy xut buffer, ta ch truy xut c tng byte, sau ta da vo
mask ca cc c c nh ngha y truy xut ti c tng ng.
Code:
#define
#define
#define
#define
#define
#define
#define
#define
#define

TCP_NON_FLAG
TCP_FIN_FLAG
TCP_SYN_FLAG
TCP_RST_FLAG
TCP_PSH_FLAG
TCP_ACK_FLAG
TCP_URG_FLAG
TCP_ECE_FLAG
TCP_CWR_FLAG

(0)
(1<<0)
(1<<1)
(1<<2)
(1<<3)
(1<<4)
(1<<5)
(1<<6)
(1<<7)

Tip theo ta quay li tcp.h, nh ngha mt s hng s s dng cho giao thc TCP
u tin l gi tr MSS (Max Segment Size Kch thc on d liu ti a m ta c th nhn). Ch ny cc bn xem li
minh ha ch 2 c th k l hiu ngha gi tr ny lin.
Code:
#define MAX_SEGMENT_SIZE (ETHERNET_BUFFER_SIZE - ETH_HEADER_LEN - IP_HEADER_LEN - TCP_HEADER_LEN)
Tip theo l nh ngha cc trng thi trong TCP (xem li phn lu chuyn i trng thi nh).
Code:
//List the TCP session state
#define TCP_STATE_CLOSED
0
#define TCP_STATE_SYN_SENT
1
#define TCP_STATE_LISTEN
2
#define TCP_STATE_SYN_RECEIVED 3
#define TCP_STATE_ESTABLISHED 4
#define TCP_STATE_FIN_WAIT1
5
#define TCP_STATE_FIN_WAIT2
6
#define TCP_STATE_CLOSING
7
#define TCP_STATE_TIMED_WAIT
8
#define TCP_STATE_CLOSE_WAIT
9
#define TCP_STATE_LAST_ACK
10

nh ngha thi gian timeout cho 1 kt ni TCP: ci ny rt quan trng, c th trong 1 phin TCP ang kt ni, cha n
giai on gii ta, nhng pha bn kia v l do no m ngng lin lc, nu ch ht Timeout ta phi gii ta kt ni
gii phng b nh.
Code:
//60 seconds timeout:
#define TCP_TIMEOUT 60
S kt ni ng thi ti a cho php:
Code:
//maximum connection count
#define TCP_MAX_SESSION 8
Tip theo ta khai bo 1 kiu struct lu thng tin v 1 kt ni:
Code:
//-------------------------------------------------------------------------------------struct tcpSession{
unsigned int desPort;
//Port on the remote host
unsigned int srcPort;
//Port on the local host
unsigned long desIP;
//IP address of the remote host
unsigned long seqNumber; //Sequence number
unsigned long ackNumber; //Acknowlegement number
unsigned char sesState; //Current state of TCP session
unsigned int srcWin;
unsigned int desWin;
unsigned long lastRxAck; //Last Received Ack
unsigned char nextAck;
unsigned char timeOut;
//Session time out
void(*appDataIn)(unsigned char* dataBuffer,unsigned int dataLen,struct tcpSession *pSession);
unsigned char appID;
//Upper layer application ID
unsigned char appState; //Upper layer application state
};
By gi chuyn sang tcp.c:
Khai bo 1 bng TCP session, trong mi dng l 1 struct tcpSession lu thng tin v 1 kt ni:
Code:
//-------------------------------------------------------------------------------------struct tcpSession tcpSessionTable[TCP_MAX_SESSION];
Vit hm khi to s tun t (sequence number) cho 1 kt ni TCP. Cc bn xem li phn minh ha (2 c th k). Mi
pha s t chn 1 s tun t bt u. Trn my tnh, con s ny thng c ly theo thi gian. y cho n gin,
ta ch chn i 1 s m thi.
Code:
//-------------------------------------------------------------------------------------//Ham khoi tao so tuan tu cho mot phien TCP
// Hien tai su dung gia tri 1234 (may tinh thuong dung gia tri thoi gian hien tai)
unsigned long TCPInitSequenceNumber()
{
return(1234);
}
Tip theo l hm ng 1 phin TCP:
Code:
//-------------------------------------------------------------------------------------//Ham dong mot phien TCP
void TCPCloseSession(unsigned char socketnum)
{
tcpSessionTable[socketnum].sesState = TCP_STATE_CLOSED;
#ifdef TCP_DEBUG
printf("Close TCP session %d\r\n",socketnum);
#endif
}
Vit hm khi to cc bin cho giao thc TCP:
Code:
//-------------------------------------------------------------------------------------//Khoi dong cac gia tri trong bang TCP session

void TCPInit()
{
unsigned char i = 0;
for(i=0; i<TCP_MAX_SESSION; i++){
TCPCloseSession(i);
}
}
Code:
Hm tm kim 1 phin TCP ang ri trong bng TCP session table ( m kt ni mi)
//-------------------------------------------------------------------------------------//Tim mot session TCP dang roi
unsigned char TCPGetFreeSession(){
unsigned char i;
for(i=0; i<TCP_MAX_SESSION; i++){
if (tcpSessionTable[i].sesState == TCP_STATE_CLOSED)
return i;
}
//no free closed socket fount! -> kick an TIMED_WAIT socket
for(i=0; i<TCP_MAX_SESSION; i++){
if (tcpSessionTable[i].sesState == TCP_STATE_TIMED_WAIT){
TCPCloseSession(i);
return i;
}
}
//no more free sockets ... return invalid val
return(TCP_MAX_SESSION);
}
Vit hm khi to mt kt ni mi ( ch server):
Code:
//-------------------------------------------------------------------------------------//Ham khoi tao mot session TCP o che do server de cho ket noi
void
TCPCreateSession(unsigned int sourcePort, prog_void* appService)
{
unsigned char i;
i = TCPGetFreeSession();
if(i >= TCP_MAX_SESSION)
i = 0; //force session 0
tcpSessionTable[i].srcPort = sourcePort;
tcpSessionTable[i].sesState = TCP_STATE_LISTEN;
//Current state of TCP session
tcpSessionTable[i].srcWin = 8192;//NETSTACK_BUFFERSIZE - ETH_HEADER_LEN - IP_HEADER_LEN TCP_HEADER_LEN - 16;
tcpSessionTable[i].desWin = tcpSessionTable[i].srcWin;
tcpSessionTable[i].timeOut = TCP_TIMEOUT;
//Session time out
tcpSessionTable[i].appDataIn = appService;
#ifdef TCP_DEBUG
printf("TCP session created: %d\r\n", i);
#endif
}
Hm kim tra Timeout ca cc phin TCP ang kt ni
Code:
//-------------------------------------------------------------------------------------//Duoc goi moi giay de kiem tra Time out cho cac phien TCP,
// giai phong cac phine TCP bi treo
void TCPCheckTimeOut(){
unsigned char i;
for(i=0; i<TCP_MAX_SESSION; i++){
//decrement ttl:
if ((tcpSessionTable[i].sesState != TCP_STATE_CLOSED) && (tcpSessionTable[i].sesState
!= TCP_STATE_LISTEN)){
if(tcpSessionTable[i].timeOut)
tcpSessionTable[i].timeOut--;
//if socket TTL count is zero, close this socket!
if (tcpSessionTable[i].timeOut == 0){
TCPCloseSession(i);
}

}
}
}
Hm tnh checksum cho gi TCP
Code:
//-------------------------------------------------------------------------------------//Tinh checksum cho goi TCP
unsigned int checksum(unsigned char *buffer, unsigned int len, unsigned long csum32)
{
unsigned int res16 = 0x0000;
unsigned char data_hi;
unsigned char data_lo;
while(len > 1){
data_hi = *buffer++;
data_lo = *buffer++;
res16 = (((unsigned int)data_hi << 8) + data_lo);
csum32 = csum32 + res16;
len -=2;
}
if(len > 0){
data_hi = *buffer;
res16
= (unsigned int)data_hi<<8;
csum32 = csum32 + res16;
}
while(csum32>>16)
csum32 = (csum32 & 0xFFFF)+ (csum32 >> 16);
//csum32 = ((csum32 & 0x0000FFFF)+ ((csum32 & 0xFFFF0000) >> 16));
res16 =~(csum32 & 0x0000FFFF);
return (res16);
}
Tip theo l hai hm chnh ca giao thc:
Hm gi 1 on d liu i bng giao thc TCP:
Code:
//-------------------------------------------------------------------------------------//Gui di mot goi TCP
void TCPPackedSend(struct tcpSession *pSession, unsigned char Flags, unsigned int len, unsigned char
*dataBuffer)
{
unsigned int tmp;
unsigned long checksum32;
//Make pointer to TCP header
struct ntTCPHeader* tcpHeader;
struct ntIPHeader* ipHeader;
//Neu dang syn thi them option ve MSS
if(Flags & TCP_SYN_FLAG){
//Option data
dataBuffer[0] = 0x02;
dataBuffer[1] = 0x04;
dataBuffer[2] = (MAX_SEGMENT_SIZE >> 8) & 0xff;
dataBuffer[3] = MAX_SEGMENT_SIZE & 0xff;
dataBuffer[4] = 0x01;
dataBuffer[5] = 0x03;
dataBuffer[6] = 0x03;
dataBuffer[7] = 0x00;
//Move data pointer to make room for TCP header
}
dataBuffer -= TCP_HEADER_LEN;
tcpHeader = (struct ntTCPHeader*)dataBuffer;
//Fill UDP header
tcpHeader->srcPort = HTONS(pSession->srcPort);
tcpHeader->desPort = HTONS(pSession->desPort);
tcpHeader->seqNumber = HTONL(pSession->seqNumber);
pSession->seqNumber = pSession->seqNumber + len;
if(Flags & (TCP_FIN_FLAG|TCP_SYN_FLAG))
(pSession->seqNumber)++;
tcpHeader->ackNumber = HTONL(pSession->ackNumber);
if(Flags & TCP_SYN_FLAG){
tcpHeader->Offset = (0x07<<4);

len += (TCP_HEADER_LEN + 8);


}else{
tcpHeader->Offset = (0x05<<4);
len += TCP_HEADER_LEN;
}
tcpHeader->Flags = Flags;
tcpHeader->Window = HTONS(pSession->srcWin);//((NETSTACK_BUFFERSIZE-20-14));
tcpHeader->Checksum = 0;
tcpHeader->UrgentPtr = 0x0000;
//Generate checksum
ipHeader = (struct ntIPHeader*)(dataBuffer-IP_HEADER_LEN);
ipHeader->srcIPAddr = HTONL(ipGetConfig()->ip);
ipHeader->desIPAddr = HTONL(pSession->desIP);
ipHeader->Checksum = HTONS(len);
ipHeader->TTL = 0x00;
ipHeader->Protocol = IP_PROTO_TCP;
checksum32 = 0;
tmp = len + 12;
tmp = checksum (((unsigned char *)ipHeader+8), tmp, checksum32);
tcpHeader->Checksum = HTONS(tmp);
ipSend(pSession->desIP, IP_PROTO_TCP, len, (unsigned char *)tcpHeader);
}
Hm x l khi nhn c 1 gi TCP
Code:
//-------------------------------------------------------------------------------------//Ham xu ly goi TCP nhan duoc, duoc goi boi giao thuc IP (IPProcess)
void TCPProcess(unsigned char *buffer, unsigned int len)
//Ham xu ly cho giao thuc TCP
// Duoc thuc thi khi nhan duoc mot goi TCP (goi boi netstackIPProcess)
// buffer: co tro den dau goi IP (bat dau IP Header)
// len
: chieu dai buffer
{
unsigned char i,ipHeaderLen,tcpHeaderLen;
unsigned int dataLen;
unsigned long tmp;
struct ntIPHeader* ipHeader;
struct ntTCPHeader* tcpHeader;
unsigned char *tcpData;
//Khoi tao cac co tro den Header IP va TCP
ipHeader = (struct ntIPHeader*)(buffer);
ipHeaderLen = ((ipHeader->verHdrLen) & 0x0F) << 2;
//
tcpHeader = (struct ntTCPHeader*)(buffer+ipHeaderLen);
tcpHeaderLen = ((tcpHeader->Offset) & 0xF0) >> 2;
//
tcpData = (buffer+ipHeaderLen+tcpHeaderLen);
dataLen = HTONS(ipHeader->Len) - (ipHeaderLen + tcpHeaderLen);
//Tim kiem mot phien TCP co san cho goi nay
for(i = 0; i < TCP_MAX_SESSION; i++){
//Check session table
if(tcpSessionTable[i].sesState != TCP_STATE_CLOSED){
//If not closed
session
if(tcpSessionTable[i].srcPort == HTONS((tcpHeader->desPort))){
//If
matched local port
if(tcpSessionTable[i].desPort == HTONS((tcpHeader>srcPort))&&(tcpSessionTable[i].desIP == HTONL((ipHeader->srcIPAddr)))){
break; //Thoat khoi vong lap for, luc nay gia tri cua i
chinh la chi so cua phien TCP tuong ung
}
}
}
}
if(i == TCP_MAX_SESSION){ //Neu khong co 1 phien TCP dang ton tai cho goi nay
//Tim 1 phien dang o trang thai LISTEN (doi ket noi) cho local port nay
for(i=0; i < TCP_MAX_SESSION; i++){
if(tcpSessionTable[i].sesState == TCP_STATE_LISTEN){
if(tcpSessionTable[i].srcPort == HTONS((tcpHeader->desPort))){
//If matched local port
//Cap nhat remote port va remote IP
tcpSessionTable[i].desPort = HTONS((tcpHeader->srcPort));
tcpSessionTable[i].desIP = HTONL((ipHeader->srcIPAddr));
//Dong thoi tao ra 1 session moi de cho ket noi khac den
local port nay

TCPCreateSession(tcpSessionTable[i].srcPort,tcpSessionTable[i].appDataIn);
break;
}
}
}
}
if(i == TCP_MAX_SESSION){
#ifdef TCP_DEBUG
printf("No TCP session found\r\n");
#endif
return; //Neu khong co phien TCP nao danh cho goi nay thi thoat ra
}
#ifdef TCP_DEBUG
printf("TCP session found: %d\r\n",i);
#endif
//Bat dau xu ly giao thuc
tcpSessionTable[i].timeOut = TCP_TIMEOUT; //Reset lai gia tri Time out
//Truong hop nhan duoc yeu cau reset lai ket noi
if ((tcpHeader->Flags) & TCP_RST_FLAG){
//Chap nhan dong ket noi
TCPCloseSession(i);
return;
}
//Kiem tra trang thai hien tai cua phien TCP
switch (tcpSessionTable[i].sesState){
//Neu la trang thai doi ket noi: TCP_STATE_LISTEN
case(TCP_STATE_LISTEN):
//Chi xu ly neu co SYN duoc set (yeu cau thiet lap ket noi)
if ((tcpHeader->Flags) == TCP_SYN_FLAG){
//Chuyen sang trang thai ke tiep la TCP_STATE_SYN_RECEIVED
tcpSessionTable[i].sesState = TCP_STATE_SYN_RECEIVED;
//Khoi tao gia tri sequence
tcpSessionTable[i].seqNumber = HTONL(TCPInitSequenceNumber());
//Ack chinh la so tuan tu nhan duoc cong 1
tcpSessionTable[i].ackNumber = HTONL((tcpHeader->seqNumber))+1;
tcpSessionTable[i].desWin = HTONS((tcpHeader->Window));
//Goi tra xac nhan va co SYN (SYN & ACK)
TCPPackedSend(&tcpSessionTable[i],(TCP_SYN_FLAG|TCP_ACK_FLAG),0,tcpData);
//Tang so tuan tu len 1
//tcpSessionTable[i].seqNumber++;
#ifdef TCP_DEBUG
printf("SYN received\r\n");
#endif
}
break;
//Neu la trang thai TCP_STATE_SYN_RECEIVED
case(TCP_STATE_SYN_RECEIVED):
//Neu co co ACK (cho ban tin SYN & ACK truoc do)
if ((tcpHeader->Flags) == TCP_ACK_FLAG){
//Kiem tra ack trong goi tin den, neu dung thi thiet lap ket noi hoan
tat

}else{

if((tcpSessionTable[i].seqNumber) == HTONL((tcpHeader->ackNumber))){
tcpSessionTable[i].sesState = TCP_STATE_ESTABLISHED;
//Goi tiep theo gui di se co co ACK
tcpSessionTable[i].nextAck = 1;
#ifdef TCP_DEBUG
printf("Connection established\r\n");
#endif
}
//Neu khong dung ACK
//Khong lam gi ca, goi tin do khong hop le
//TCPCloseSession(i);

}
break;
//Truong hop ket noi da duoc thiet lap
case(TCP_STATE_ESTABLISHED):
//Neu nhan duoc yeu cau ket thuc ket noi tu client
if ((tcpHeader->Flags) & TCP_FIN_FLAG){
//Chuyen sang trang thai ke tiep la trang thai cho ACK cuoi
//Dung ra o day phai chuyen sang trang thai TCP_STATE_CLOSE_WAIT
nhung khong can thiet

//

vi o day ta co the dong ket noi ngay ma khong can cho gui xong du

lieu
tcpSessionTable[i].sesState = TCP_STATE_LAST_ACK;
//Cap nhat ack
tcpSessionTable[i].ackNumber = HTONL((tcpHeader->seqNumber)) +
dataLen;
tcpSessionTable[i].ackNumber++;
//Tang 1 cho co FIN
//Gui xac nhan ACK cho yeu cau dong ket noi dong thoi thong bao san
sang dong ket noi
TCPPackedSend(&tcpSessionTable[i],TCP_ACK_FLAG,0,tcpData);
TCPPackedSend(&tcpSessionTable[i],(TCP_FIN_FLAG|TCP_ACK_FLAG),0,tcpData);
//Dang le truyen o trang thai CLOSE_WAIT nhung ta thuc hien o day
luon
TCPCloseSession(i);
//Neu khong (dang truyen du lieu)
}else{
//Kiem tra ACK tu remote host
if((tcpHeader->Flags) & TCP_ACK_FLAG){

//Neu co co ACK thi kiem

tra gia tri ACK


tcpSessionTable[i].lastRxAck = HTONL((tcpHeader>ackNumber));
if ((tcpSessionTable[i].seqNumber) == HTONL((tcpHeader>ackNumber))){

//Dung ACK

}else{

#ifdef TCP_DEBUG
printf("Got ACK\r\n");
#endif
//Phia ben kia khong nhan duoc du thong tin
//Sua loi o day
//Process error correction here
//Not finish yet, temporary just ignore it and

continue with next data


//Chua thuc hien
tcpSessionTable[i].seqNumber = HTONL((tcpHeader>ackNumber));
#ifdef TCP_DEBUG
printf("Miss ACK:got
%d\r\nExpected:%d\n\r",HTONL((tcpHeader->ackNumber)),tcpSessionTable[i].seqNumber+1);
#endif
}
}
//--Ket thuc kiem tra ACK
//Kiem tra sequence number
tmp = HTONL((tcpHeader->seqNumber));
//Neu khong dung goi dang cho nhan
if (tmp != tcpSessionTable[i].ackNumber){
//there was an error, check what to do next:
#ifdef TCP_DEBUG
printf("Incorrect seq,
got:%d,expexted:%d\r\n",tmp,tcpSessionTable[i].ackNumber);
#endif
if (tmp < tcpSessionTable[i].ackNumber){
//Neu dang doi du lieu bat dau tu byte thu n nhung
ta nhan duoc doan du lieu bat dau tu (n-k)
//Tinh phan du lieu thua (k = n - (n-k))
tmp = (tcpSessionTable[i].ackNumber - tmp);
//Neu doan du lieu thua it hon du lieu nhan duoc
if(tmp < dataLen){
//Bo di phan du lieu thua, nhan phan con
lai
tcpData += tmp;
dataLen = dataLen - tmp;
}else{ //Neu tat ca du lieu nhan duoc deu thua
//Gui lai ACK, bo goi vua nhan duoc
dataLen = 0;
TCPPackedSend(&tcpSessionTable[i],(TCP_ACK_FLAG),0,tcpData);
return;
}
//Neu seq > ack (tuc la co 1 doan du lieu bi mat)
}else{ //tmp > tcp....
//Yeu cau gui lai
TCPPackedSend(&tcpSessionTable[i],(TCP_ACK_FLAG),0,tcpData);

return;
}
}
//Neu thuc thi den day nghia la sequence number == ack number (chinh
xac)
//--Ket thuc kiem tra so tuan tu
//Kiem tra chieu dai buffer de chac chan la chieu dai du lieu nhan
duoc khong qua buffer
//
if (tcpData > (buffer + ETHERNET_BUFFER_SIZE))
tcpData = (buffer + ETHERNET_BUFFER_SIZE);
if ((tcpData + dataLen) > buffer + ETHERNET_BUFFER_SIZE){
dataLen = (buffer + ETHERNET_BUFFER_SIZE) - tcpData;
}
//
//Cap nhat ack cho lan nhan ke tiep
tcpSessionTable[i].ackNumber = tcpSessionTable[i].ackNumber +
dataLen;
#ifdef TCP_DEBUG
printf("Data length (%d), buffer size(%d)\n\r",dataLen,(buffer +
ETHERNET_BUFFER_SIZE - tcpData));
printf("Ack Number (%d)\n\r",tcpSessionTable[i].ackNumber);
#endif
//Goi tiep theo gui di se co co ACK
tcpSessionTable[i].nextAck = 1;
//Goi ham xu ly lop ung dung
if(dataLen != 0){
(tcpSessionTable[i].appDataIn)(tcpData,
dataLen,&tcpSessionTable[i]);
}
}
//--Ket thuc xu ly truong hop dang truyen du lieu
break;
//Neu la trang thai doi LAST_ACK (2 phia deu san sang dong ket noi, dang doi xac nhan
ack cuoi cung)
case(TCP_STATE_LAST_ACK):
//socket is closed
tmp = HTONL((tcpHeader->seqNumber));
//Kiem tra ACK, neu dung ACK
if (tmp == tcpSessionTable[i].seqNumber + 1){
TCPCloseSession(i);
}else{
//Gui lai co FIN & ACK
TCPPackedSend(&tcpSessionTable[i], (TCP_FIN_FLAG|TCP_ACK_FLAG), 0,
tcpData);
}
break;
//Truong hop ngat ket noi thu dong, da nhan co FIN tu remote host va xac nhan
case(TCP_STATE_CLOSE_WAIT):
//Truong hop nay se khong xay ra vi o tren ta chuyen truc tiep
// sang LAST_ACK khi nhan duoc yeu cau dong ket noi
tcpSessionTable[i].sesState = TCP_STATE_LAST_ACK;
if(dataLen){
tcpSessionTable[i].ackNumber = HTONL((tcpHeader->seqNumber)) +
dataLen;
}else{

//Neu dataLen == 0 thi cung tang so tuan tu len 1


tcpSessionTable[i].ackNumber = HTONL((tcpHeader->seqNumber))+1;

}
//tcpSessionTable[i].seqNumber = HTONL((tcpHeader->ackNumber));
TCPPackedSend(&tcpSessionTable[i], (TCP_FIN_FLAG|TCP_ACK_FLAG), 0, tcpData);
break;
//Truong hop dang o trang thai FIN WAIT 1 (da truyen du lieu xong,
// san sang dong ket noi va da gui di co FIN va dang cho ACK)
case(TCP_STATE_FIN_WAIT1):
//if we receive FIN
tcpSessionTable[i].ackNumber = HTONL((tcpHeader->seqNumber))+1;
if (tcpHeader->Flags == TCP_FIN_FLAG){
//Neu chi nhan duoc co FIN
//Chuyen sang trang thai CLOSING va gui ACK
tcpSessionTable[i].sesState = TCP_STATE_CLOSING;
TCPPackedSend(&tcpSessionTable[i], (TCP_ACK_FLAG), 0, tcpData);
//tcpSessionTable[i].seqNumber++;
#ifdef TCP_DEBUG
printf("Closing\n\r");

#endif
}else if(tcpHeader->Flags == (TCP_FIN_FLAG | TCP_ACK_FLAG)){

//Neu

nhan dong thoi FIN va ACK


//Chuyen sang trang thai TIME_WAIT va gui ACK
// nhung o day do chua co timer nen ta chuyen luon sang dong ket noi
if (HTONL((tcpHeader->ackNumber)) == tcpSessionTable[i].seqNumber){
//TCPPackedSend(&tcpSessionTable[i], (TCP_ACK_FLAG), 0,
tcpData);

}else{

TCPCloseSession(i);
#ifdef TCP_DEBUG
printf("End\n\r");
#endif
//Neu khong dung ack cho thong bao FIN
//Chuyen sang cho co ACK cuoi cung
tcpSessionTable[i].sesState = TCP_STATE_LAST_ACK;
#ifdef TCP_DEBUG
printf("Last ack\n\r");
#endif

}
//Gui xac nhan cho co FIN
TCPPackedSend(&tcpSessionTable[i], (TCP_ACK_FLAG), 0, tcpData);
//tcpSessionTable[i].seqNumber++;
}else if(tcpHeader->Flags == TCP_ACK_FLAG){
//Neu chi nhan duoc ACK
//Chuyen sang trang thai FIN WAIT2
tcpSessionTable[i].sesState = TCP_STATE_FIN_WAIT2;
#ifdef TCP_DEBUG
printf("Fin wait 2\n\r");
#endif
}
break;
//Neu dang o trang thai FIN WAIT 2 (san sang dong ket noi va gui co FIN,
// phia ben kia da xac nhan nhung van chua san sang dong ket noi
case(TCP_STATE_FIN_WAIT2):
//Neu nhan duoc co FIN
if (tcpHeader->Flags & TCP_FIN_FLAG){
if(dataLen){
tcpSessionTable[i].ackNumber = HTONL((tcpHeader>seqNumber))+dataLen;
}else{
tcpSessionTable[i].ackNumber = HTONL((tcpHeader>seqNumber))+1;
}
//FIN -> goto TIMED WAIT
tcpSessionTable[i].sesState = TCP_STATE_TIMED_WAIT;
TCPPackedSend(&tcpSessionTable[i], (TCP_ACK_FLAG), 0, tcpData);
//Chua co timer thi dong ket noi o day luon
TCPCloseSession(i);
#ifdef TCP_DEBUG
printf("End\n\r");
#endif
}
break;
case(TCP_STATE_TIMED_WAIT):
break;
case(TCP_STATE_CLOSING):
tcpSessionTable[i].sesState = TCP_STATE_TIMED_WAIT;
break;
default:
TCPCloseSession(i);
}
//we must set timed wait TTL here because timed wait is not packet triggered
if (tcpSessionTable[i].sesState == TCP_STATE_TIMED_WAIT){
tcpSessionTable[i].timeOut = 5; //5 seconds timeout
}
return;
}
//-------------------------------------------------------------------------------------Hai hm ny khip qu, nhn v thy oi ri, t t gii thch, khng hiu sao hi xa mnh li vit phc tp nh vy.
Hay l mi ngi c t t nghin cu, ch no khng hiu th c hi
qu. Vit gii thch cho code c khi cn kh hn vit code

. Gi ngh ti vit gii thch cho code thy nn

Giao thc UDP:


Tip theo, ta chuyn sang giao thc UDP, trong 3 giao thc lp ny (TCP, UDP v ICMP) th UDP l giao thc n gin
nht, d vit nht.
Trong chng giao thc IP, nhim v ca UDP l khi nhn 1 segment d liu t ng dng gi xung, n s gi i ngay n
a ch IP v port c yu cu m khng cn nh s th t, bt tay thit lp kt ni hay thm ch khng quan tm n
vic d liu c n c ch hay khng.
Header ca giao thc UDP rt on gin: ch gm c 4 trng: port ngun, port ch, chiu di gi tin v checksum.

Trong thc t, UDP c s dng gi i cc d liu m yu cu v tr nh quan trng hn yu cu v tin cy. V


d nh d liu ca cc video stream, audio stream, cc bo hiu nhanh, hay n gin l tng tc trong cc game online.
Vy ta m file packet.h thm khai bo header UDP vo:
Code:
//-------------------------------------------------------------------------------------//Cau truc UDP header
struct ntUDPHeader
{
unsigned int
srcPort;
unsigned int
desPort;
unsigned int
Len;
unsigned int
Checksum;
};
#define UDP_HEADER_LEN
8
Sau to file source v header tng ng:
udp.c
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ip.h"
#include "uart.h"
udp.h
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef
UDP_H
#define UDP_H
//---------------------------------------------------------------------------#endif

//UDP_H

Ta ch vit 2 hm cho giao thc UDP:


Hm gi gi tin bng UDP:
Code:
//---------------------------------------------------------------------------//Ham gui di mot goi UDP
void udpSend(unsigned long dstIp, unsigned int dstPort, unsigned int len, unsigned char* udpData)
{
struct ntUDPHeader* udpHeader;
udpHeader = (struct ntUDPHeader*)(udpData - UDP_HEADER_LEN);
len += UDP_HEADER_LEN;
udpHeader->desPort = HTONS(dstPort);
udpHeader->srcPort = HTONS(dstPort);
udpHeader->Len = HTONS(len);
udpHeader->Checksum = 0;
ipSend(dstIp, IP_PROTO_UDP, len, (unsigned char*)udpHeader);

}
Hm x l gi tin nhn c:
Code:
//-------------------------------------------------------------------------------------//Ham xu ly goi UDP nhan duoc, duoc goi boi ham xu ly goi IP (IPProcess)
// Hien chua co ung dung chay UDP nen ham nay trong
void UDPProcess(unsigned int len, struct ntIPHeader* packet)
{
dhcpIn((len - IP_HEADER_LEN - UDP_HEADER_LEN), (struct netDhcpHeader*)((char*)packet IP_HEADER_LEN - UDP_HEADER_LEN));
#ifdef NET_DEBUG
printf("NetStack UDP/IP Rx Dummy Handler\r\n");
#endif
}
V trong project ny, chng ta ch s dng UDP cho 1 ng dng duy nht l DHCP nn y ta ch gi hm dhcpIn x
l. Hm ny ta vn cha vit nh. Nu ta cn dng UDP cho cc giao thc khc th phc tp hn 1 t, tuy nhin vn n
gin hn nhiu so vi TCP.
Tip theo s l DHCP v HTTP, xong ci ny l cc bn c th truy cp web trn mch c ri (nu c mch

).

Gii thch cho 2 hm chnh trong giao thc TCP:


Hm TCPPackedSend:
Code:
void TCPPackedSend(struct tcpSession *pSession, unsigned char Flags, unsigned int len, unsigned char
*dataBuffer)
Trong ny:
- pSession l con tr, tr n struct tcpSession trong bng TCP Session Table tng ng vi phin kt ni TCP m ta
mun gi gi tin i (trong phn lp trnh giao thc TCP ny, ta h tr vic AVR ng thi theo di v truyn data vi
nhiu kt ni (nhiu client) cng lc).
- Flags l cc c tng ng m ta mun set trong header TCP
- len: chiu di buffer d liu ng dng.
- dataBuffer: buffer cha d liu ng dng.
Cu trc frame d liu m ENC28J60 s gi i nh sau:

Lc ny, dataBuffer ang tr n phn Application Data trong frame trn, bin len ang l chiu di phn data ny.
Khai bo cc bin s dng trong hm:
Code:
unsigned int tmp;
unsigned long checksum32;
Lc ny, trn buffer (dataBuffer) c d liu ng dng (phn Application Data), nhim v ca giao thc TCP l phi xy
dng header TCP cho frame d liu ny.
Tip theo, ta khai bo 2 con tr, tr n vng IP Header v TCP Header (mi khai bo, cha gn a ch):
Code:
struct ntTCPHeader* tcpHeader;
struct ntIPHeader* ipHeader;
Nu l ang trong giai on thit lp kt ni (c SYN c set) th TCP Header s c thm trng Option, cha gi tr MSS
(Max Segment Size), ta ghi lun vo vng buffer dnh cho Application Data, v khi SYN th vng ny khng c (cc bn
tin thit lp kt ni khng cha d liu ng dng).
Code:
if(Flags & TCP_SYN_FLAG){
//Option data
dataBuffer[0] = 0x02;
dataBuffer[1] = 0x04;
dataBuffer[2] = (MAX_SEGMENT_SIZE >> 8) & 0xff;

dataBuffer[3]
dataBuffer[4]
dataBuffer[5]
dataBuffer[6]
dataBuffer[7]

=
=
=
=
=

MAX_SEGMENT_SIZE & 0xff;


0x01;
0x03;
0x03;
0x00;

}
By gi ta dch lui con tr dataBuffer 1 on bng chiu di TCP Header v tr tcpHeader n phn u on ny.
Code:
dataBuffer -= TCP_HEADER_LEN;
tcpHeader = (struct ntTCPHeader*)dataBuffer;
in cc trng cho TCP Header:
- Source port v Des port ly t thng tin v session tng ng:
Code:
tcpHeader->srcPort = HTONS(pSession->srcPort);
tcpHeader->desPort = HTONS(pSession->desPort);
- S tun t cng vy:
Code:
tcpHeader->seqNumber = HTONL(pSession->seqNumber);
Sau ta phi tng s tun t ln ty theo chiu di d liu:
Code:
pSession->seqNumber = pSession->seqNumber + len;
Lu (ch ny lc vit code mnh b sai, debug mt c bui ti): tuy cc bn tin SYN v FIN khng cha d liu,
n vn c xem l c chiu di d liu 1 byte, phi tng s tun t ln 1 i vi cc bn tin ny:
Code:
if(Flags & (TCP_FIN_FLAG|TCP_SYN_FLAG))
(pSession->seqNumber)++;
S ACK:
Code:
tcpHeader->ackNumber = HTONL(pSession->ackNumber);
Nu c c SYN, nh ni trn Header TCP s c trng Option chiu di 8 byte, do ta phi ghi gi tr tng ng cho
trng Offset, v tng bin len ln tng ng:
Code:
if(Flags & TCP_SYN_FLAG){
tcpHeader->Offset = (0x07<<4);
len += (TCP_HEADER_LEN + 8);
Nu khng, chiu di TCP Header l mc nh ( nh ngha TCP_HEADER_LEN)
Code:
}else{
tcpHeader->Offset = (0x05<<4);
len += TCP_HEADER_LEN;
}
Ghi gi tr cc c
Code:
tcpHeader->Flags = Flags;
Gi tr trng Window
Code:
tcpHeader->Window = HTONS(pSession->srcWin);//((NETSTACK_BUFFERSIZE-20-14));
Tm thi gn checksum = 0 (ta s tnh TCP checksum sau)
Code:

tcpHeader->Checksum = 0;
Con tr khn khng s dng:
Code:
tcpHeader->UrgentPtr = 0x0000;
Tr n bin con tr ipHeader n vng IP Header trn buffer:
Code:
ipHeader = (struct ntIPHeader*)(dataBuffer-IP_HEADER_LEN);
Gn tm thi 1 s gi tr cn thit cho IP Header tnh checksum:
Code:
ipHeader->srcIPAddr = HTONL(ipGetConfig()->ip);
ipHeader->desIPAddr = HTONL(pSession->desIP);
ipHeader->Checksum = HTONS(len);
ipHeader->TTL = 0x00;
ipHeader->Protocol = IP_PROTO_TCP;
y cc bn cn tm hiu thm cch tnh checksum TCP, n khng ch tnh checksum phn TCP Header v d liu m
cn tnh thm 1 s trng ca IP trong 1 header IP gi, do ta phi gn tm cc trng ny ln buffer th mi tnh c
TCP checksum, cn tht ra Header IP xung giao thc IP s c xy dng li (hm ipSend).
Tnh checksum v ghi vo trng checksum ca Header TCP
Code:
checksum32 = 0;
tmp = len + 12;
tmp = checksum (((unsigned char *)ipHeader+8), tmp, checksum32);
tcpHeader->Checksum = HTONS(tmp);
Gi hm ipSend yu cu giao thc IP gi gi tin i.
Code:
ipSend(pSession->desIP, IP_PROTO_TCP, len, (unsigned char *)tcpHeader);
Hm TCPProcess:
Hm ny di qu nn ch gii thch cu trc hm cho cc bn d c thi:
Khai bo cc bin s dng:
Code:
unsigned char i,ipHeaderLen,tcpHeaderLen;
unsigned int dataLen;
unsigned long tmp;
struct ntIPHeader* ipHeader;
struct ntTCPHeader* tcpHeader;
unsigned char *tcpData;
Tr cc bin con tr header IP v TCP n vng header tng ng. Lc ny trn buffer c y frame d liu c t
ENC28J60.
Code:
//Khoi tao cac co tro den Header IP va TCP
ipHeader = (struct ntIPHeader*)(buffer);
ipHeaderLen = ((ipHeader->verHdrLen) & 0x0F) << 2;
//
tcpHeader = (struct ntTCPHeader*)(buffer+ipHeaderLen);
tcpHeaderLen = ((tcpHeader->Offset) & 0xF0) >> 2;
//
tcpData = (buffer+ipHeaderLen+tcpHeaderLen);
dataLen = HTONS(ipHeader->Len) - (ipHeaderLen + tcpHeaderLen);
Sau khi c c a ch IP ngun ca host gi v port ngun, port ch, ta tm kim trong TCP session table phin TCP c
sn tng ng vi gi tin ny, nu cha tn ti th khi to session mi:
Code:
if(i == TCP_MAX_SESSION){ //Neu khong co 1 phien TCP dang ton tai cho goi nay
//Tim 1 phien dang o trang thai LISTEN (doi ket noi) cho local port nay
for(i=0; i < TCP_MAX_SESSION; i++){
if(tcpSessionTable[i].sesState == TCP_STATE_LISTEN){

if(tcpSessionTable[i].srcPort == HTONS((tcpHeader->desPort))){
//If matched local port
//Cap nhat remote port va remote IP
tcpSessionTable[i].desPort = HTONS((tcpHeader->srcPort));
tcpSessionTable[i].desIP = HTONL((ipHeader->srcIPAddr));
//Dong thoi tao ra 1 session moi de cho ket noi khac den
local port nay
TCPCreateSession(tcpSessionTable[i].srcPort,tcpSessionTable[i].appDataIn);
break;
}
}
}
}
if(i == TCP_MAX_SESSION){
#ifdef TCP_DEBUG
printf("No TCP session found\r\n");
#endif
return; //Neu khong co phien TCP nao danh cho goi nay thi thoat ra
}
#ifdef TCP_DEBUG
printf("TCP session found: %d\r\n",i);
#endif
Ta reset bin Timeout mi khi nhn c gi tin. Bin ny nhm pht hin v hy b cc phin TCP b treo mt thi
gian di m khng nhn c d liu.
Code:
tcpSessionTable[i].timeOut = TCP_TIMEOUT; //Reset lai gia tri Time out
Nu c RST=1 (Reset). ng kt ni.
Code:
if ((tcpHeader->Flags) & TCP_RST_FLAG){
//Chap nhan dong ket noi
TCPCloseSession(i);
return;
}
Tip theo, ta phi x l theo lu trng thi ca TCP. Ta dng 1 cu trc switchcase x l ty vo trng thi hin
ti ca kt ni:
Code:
switch (tcpSessionTable[i].sesState){
//Neu la trang thai doi ket noi: TCP_STATE_LISTEN
case(TCP_STATE_LISTEN):
break;
//Neu la trang thai TCP_STATE_SYN_RECEIVED
case(TCP_STATE_SYN_RECEIVED):
break;
//Truong hop ket noi da duoc thiet lap
case(TCP_STATE_ESTABLISHED):
break;
//Neu la trang thai doi LAST_ACK (2 phia deu san sang dong ket noi, dang doi xac nhan
ack cuoi cung)
case(TCP_STATE_LAST_ACK):
break;
//Truong hop ngat ket noi thu dong, da nhan co FIN tu remote host va xac nhan
case(TCP_STATE_CLOSE_WAIT):
break;
//Truong hop dang o trang thai FIN WAIT 1 (da truyen du lieu xong,
// san sang dong ket noi va da gui di co FIN va dang cho ACK)
case(TCP_STATE_FIN_WAIT1):
break;
//Neu dang o trang thai FIN WAIT 2 (san sang dong ket noi va gui co FIN,
// phia ben kia da xac nhan nhung van chua san sang dong ket noi
case(TCP_STATE_FIN_WAIT2):
break;
case(TCP_STATE_TIMED_WAIT):
break;
case(TCP_STATE_CLOSING):
break;
default:

TCPCloseSession(i);
}
Trong mi trng thi, ta x l thng tin trong header TCP v chuyn trng thi tng ng. Mi ngi t c nh

Bi 6: Cc giao thc lp ng dng


Giao thc DHCP:
- DHCP l mt giao thc c s dng phn phi ng cc tham s cu hnh TCP/IP cho cc my tnh. Mt DHCP
server c th cho client DHCP mt s thit lp TCP/IP, nh l a ch IP, subnet mask, v my ch DNS.
- Mi client s nhn mt hp ng thu a ch trong thi gian hn nh. Nu client khng cn s dng a ch khi hp
ng thu ht hn, a ch c th cp pht cho cc client khc.
C ch lm vic ca DHCP: gm c 4 bn tin chnh:
+ DHCPDISCOVER: DHCP client khi to tin trnh bng cch qung b mt gi ti cng UDP 68 (s dng cho my ch
BOOTP v DHCP). Gi u tin ny c gi l bn tin DHCP Discover, n s yu cu bt c DHCP server no nhn c
gi thc hin vic cu hnh. Gi DHCP discover gm rt nhiu trng, nhng mt vng quan trng nht cha a ch vt l
ca DHCP client.

+ DHCPOFFER: Mt DHCP server c cu hnh cung cp hp ng a ch cho mng m client c tr s p ng li mt


gi tn l DHCP offer v gi n di dng qung b ti my a ra DHCP discover. Thng ip qung b ny c gi ti
cng UDP 67 v bao gm a ch vt l ca client, a ch vt l v a ch IP ca DHCP server, cng nh gi tr a ch IP
v subnet mask cung cp cho DHCP client.

+ DHCPREQUEST: Client chn mt DHCP offer, to mt gi DHCP request v qung b gi ny. Gi DHCP request ny bao
gm a ch IP ca server pht ra DHCP offer v a ch vt l ca DHCP client. DHCP request ny thc hin hai vic:
. Bo cho DHCP server c chn rng n yu cu mt a ch IP.
. Thng bo cho cc DHCP server khc l DHCP offer ca chng khng c chp nhn.

+ DHCPACK: Khi DHCP server c chn nhn c DHCP request, n s tr li bng gi DHCP ack. DHCP ack bao gm
a ch IP v subnetmask cho DHCP client. Ngoi cc thng tin v a ch IP, DHCP client c th nhn thm cc thng tin

cu hnh nh a ch IP ca gateway, my ch DNS, ...

Nguyn vn bi tienhuypro
Hi anh Tm ! V em khng phi l dn IT nn c nhiu thc mc lm.
Cho em hi l trng hp gi ra ngoi mng LAN. phn 4a sau khi bit MAC ca gateway ri phn gi tin cn gi n 203.162.44.164 th
s thc hin nh th no vy.
Cu hi th 2: C khi no 2 a ch MAC trng nhau khng v nu trng th c phi lp IP dng phn bit cc my tnh vi nhau khng.
Cu 1: Sau khi bit MAC ca gateway, host s gi gi IP n Gateway thng qua a ch MAC ca n (a ch IP ch vn
ghi l 203.162.44.164 nhng a ch MAC ch th l ca Gateway).
Khi nhn c gi tin, Gateway (chnh l 1 router IP) s kim tra a ch mng ca a ch IP ch (VD: trng hp a ch
IP 203.162.44.164 th a ch mng l 203.162.44.0 - 24 bit u). Sau n i chiu a ch mng ny vi mt bng,
gi l bng nh tuyn (Routing table). Trong bng nh tuyn c lu thng tin v cc a ch mng v giao tip mng
tng ng m gi tin phi c chuyn ti, cng nh a ch IP ca Router tip theo s chu trch nhim chuyn gi tin i.
Gateway s cn c vo cc thng tin ny chuyn gi tin i tip.
V d: ADSL router nh mnh c bng nh tuyn nh sau (c th truy cp vo trang cu hnh modem xem c bng
ny):

Gii thch:
- Destination: a ch ch, thng ch lu a phn ch mng.
- Subnet Mask: mt n mng con tng ng vi a ch ch .
- Next hop: router k tip s nhn nhim v chuyn gi tin.
- Metric: s chng (s router) m gi tin phi i qua n c ch ny (s dng cho cc giao thc nh tuyn).
- Interface: giao din (hay kt ni mng) m router phi chuyn gi tin ra. Trong trng hp ADSL router ca mnh,
n ch c 2 interface: kt ni vo mng LAN bn trong (n t tn l br0) v kt ni ra bn ngoi (n t tn l ppp0).

1-Dng u tin cho bit: nu a ch ch l 123.20.128.1 (y chnh l a ch ca Router bin ca ISP m ADSL router
ca mnh kt ni n), th n cn chuyn d liu ra giao tip (interface) ppp0 (y chnh l kt ni WAN ca modem
ADSL, xem thm cc minh ha s mng bn di). Next hop= * c ngha l n khng cn thng qua router no khc
na m c kt ni trc tip n destination.
2-Dng th 2: nu ch l 192.168.0 (y l a ch ca mng LAN), th n phi chuyn gi tin vo giao tip mng LAN
bn trong (interface = br0). Tng t, khng c Next hop.
3-Dng th 3: nu ch l 127.0.0.0 (y l a ch loopback, gi cho chnh mnh) th n khng chuyn ra giao tip no
ht m l cho chnh n (Interface = lo).
4-Dng th 4: Mi trng hp a ch ch khc (Destination = 0.0.0.0; Subnet Mask = 0.0.0.0), n s chuyn ra giao
tip mng bn ngoi (Interface = ppp0), v gi n router k tip s chu trch nhim chuyn gi tin i l router bin ca
ISP (a ch l 123.20.128.1)
V d minh ha:
y l s mng (a ch IP ca cc Router li ch la minh ha, khng chnh xc v mnh khng c cc thng tin ny)

Bc 1: sau khi Gateway (ADSL router) nhn c gi tin c a ch ch l 203.162.44.164, n s tra bng T ca n v
thy tng ng vi dng ny (destination = 0.0.0.0), n s chuyn gi tin ra giao tip mng WAN (ppp0) n router k
tip l 123.20.128.1 (bng cch ghi a ch MAC ca router k tip vo phn destination MAC Address trong frame
ethernet).

Bc 2: Router bin ca ISP (123.20.128.1) nhn gi tin, tra trong bng T ca n, tm dng tng ng, cn c vo
n chuyn gi tin ra interface s 1 ca n (kt ni ti router li) v gi n cho router li (123.20.64.1).

Bc 3: Router li ny nhn gi tin, li tra bng T ca n, sau chuyn gi tin ra interface 3 ca n n router li th
hai (123.20.66.1).

Bc 4: Tng t, router li th hai nhn gi tin, tra bng v chuyn n router k l router bin th hai (123.20.66.5)
qua interface 3 ca n.

Bc 5: Cui cng, n lt router bin ng ra nhn gi tin, tra bng T, chuyn gi n thng ch m khng cn qua
router no na.

Cu 2: V l thuyt, mi nh sn xut c sn xut thit b mng s c cp mt khong a ch MAC (cc byte u trong
a ch MAC t 1 nh sn xut s ging nhau. V d: 3 byte u ca 3com l: 00A024, ca Apple l 00A040,...). Sau
khi sn xut ra mi thit b, nh sn xut s nh s a ch MAC ca chng khc nhau. Nh vy, v l thuyt, a ch
MAC khng trng nhah.
Tuy nhin rt nhiu thit b (VD IC ENC28J60, nhiu loi card mng my tnh) cho php thay i a ch MAC, do trong
thc t, vic trng a ch MAC hon ton c th xy ra. Trong trng hp : v d trong mng LAN c 2 my trng a
ch MAC, khi d liu c gi lp truy nhp mng (switch hay hub chuyn i) th ng thi c 2 my u nhn c
nu d liu gi cho 1 trong 2 my. Tuy nhin khi d liu c chuyn ln lp IP, a ch IP s c kim tra (c th xem
code ca phn giao thc IP thy vic kim tra ny), nu khng ng a ch IP, d liu s b b qua.
Nu 2 my tnh trng a ch MAC nm 2 mng LAN khc nhau, vic ny s khng nh hng g, v khi chuyn d liu
gia cc mng LAN s do router thc hin, m nh ni trn, router s cn c vo a ch IP ch khng phi a ch
MAC.
Hy vng cu tr li ca mnh gii p c thc mc ca Huy, nu cha r c hi tip nh. Mnh c cc slide vi
animation minh hot cc hot ng ny, nhng khng bit lm sao post ln, v dd khng h tr post flash th phi.
L hn lu, hm nay tip tc vi giao thc DHCP, cn thng ny vi HTTP na l xong.
Trc ht, ta li to 2 file source v header:
"dhcp.c"
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ethernet.h"
#include "ip.h"
#include "udp.h"
#include "dhcp.h"
#include "uart.h"
#include "ntAVRnet.h"
//
"dhcp.h"
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM

//---------------------------------------------------------------------------#ifndef DHCP_H
#define DHCP_H
#include "packet.h"
//#define DHCP_DEBUG
Trong file Header, ta khai bo cc Header BOOTP v DHCP:
Code:
//---------------------------------------------------------------------------/// BOOTP Header
struct ntBootpHeader
{
unsigned char
opcode;
//Message op-code / message type
unsigned char
hwaddrtype;
//Hardware address type
(Ethernet=1)
unsigned char
hwaddrlen;
//Hardware address length (Ethernet=6 byte MAC addr)
unsigned char
hops;
//hop count (client set to zero)
unsigned long
transid;
//Transaction ID (randomly chosen by client, must remain
same)
unsigned int
secs;
//Seconds elapsed since DHCP negotiation began
(filled by client)
unsigned int
flags;
//Flags
unsigned long
clipaddr;
//Client IP address (filled only if already bound,
renewing, or rebinding)
unsigned long
yoipaddr;
//Your IP address (client)
unsigned long
seipaddr;
//Server IP address
unsigned long
gwipaddr;
//Gateway IP address
unsigned char
clhwaddr[16];
//Client Hardware Address
unsigned char
sename[64];
//Server Host Name
unsigned char
file[128];
//Boot file name (null-term string)
};
//
#define BOOTP_HEADER_LEN
236
//length of BOOTP header not including options
//
#define BOOTP_OP_BOOTREQUEST
1
//BOOTP Request operation (message from client to server)
#define BOOTP_OP_BOOTREPLY
2
//BOOTP Reply operation (message from server to
client)
//
#define BOOTP_HTYPE_ETHERNET
1
//Hardware type for ethernet protocol
#define BOOTP_HLEN_ETHERNET
6
//Length of ethernet MAC address
//---------------------------------------------------------------------------struct netDhcpHeader
{
struct ntBootpHeader bootp;
//BOOTP header
unsigned long
cookie;
//magic cookie value
unsigned char
options[1];
//DHCP options
};
//
#define DHCP_HEADER_LEN
240
//length of DHCP header not including options
Tip theo ta nh ngha 1 s gi tr hng c qui nh cho cc trng trong header:
Code:
//Code for DHCP option field
#define DHCP_OPT_PAD
#define DHCP_OPT_NETMASK
#define DHCP_OPT_ROUTERS
#define DHCP_OPT_TIMESERVERS
#define DHCP_OPT_NAMESERVERS
#define DHCP_OPT_DNSSERVERS
#define DHCP_OPT_HOSTNAME
#define DHCP_OPT_DOMAINNAME
#define DHCP_OPT_REQUESTEDIP
#define DHCP_OPT_LEASETIME
#define DHCP_OPT_DHCPMSGTYPE
#define DHCP_OPT_SERVERID
#define DHCP_OPT_PARAMREQLIST
#define DHCP_OPT_RENEWALTIME
#define DHCP_OPT_REBINDTIME
#define DHCP_OPT_CLIENTID
#define DHCP_OPT_END
//Code for DHCP message type

1
3
4
5
12
50
53
54
55
58
61

0
//token padding value (make be skipped)
//subnet mask client should use (4 byte mask)
//routers client should use (IP addr list)
//time servers client should use (IP addr list)
//name servers client should use (IP addr list)
6
//DNS servers client should use (IP addr list)
//host name client should use (string)
15
//domain name client should use (string)
//IP address requested by client (IP address)
51
//DHCP Lease Time (uint32 seconds)
//DHCP message type (1 byte)
//Server Identifier (IP address)
//Paramerter Request List (n OPT codes)
//DHCP Lease Renewal Time (uint32 seconds)
59
//DHCP Lease Rebinding Time (uint32 seconds)
//DHCP Client Identifier
255 //token end value (marks end of options list)

#define DHCP_MSG_DHCPDISCOVER
1
//DISCOVER is broadcast by client to solicit OFFER from
any/all DHCP servers.
#define DHCP_MSG_DHCPOFFER
2
//OFFER(s) are made to client by server to offer IP
address and config info.
#define DHCP_MSG_DHCPREQUEST
3
//REQUEST is made my client in response to best/favorite
OFFER message.
#define DHCP_MSG_DHCPDECLINE
4
//DECLINE may be sent by client to server to indicate IP
already in use.
#define DHCP_MSG_DHCPACK
5
//ACK is sent to client by server in confirmation of
REQUEST, contains config and IP.
#define DHCP_MSG_DHCPNAK
6
//NAK is sent to client by server to indicate problem with
REQUEST.
#define DHCP_MSG_DHCPRELEASE
7
//RELEASE is sent by client to server to relinquish DHCP
lease on IP address, etc.
#define DHCP_MSG_DHCPINFORM
8
//INFORM is sent by client to server to request
config info, IP address configured locally.
nh ngha port UDP c qui nh dnh cho giao thc BOOTP v DHCP, v gi tr timeout (s giy ch tr li sau khi gi
DHCP discover), s ln c gng nhn a ch IP thng qua DHCP:
Code:
#define
#define
//
#define
#define

DHCP_UDP_SERVER_PORT
DHCP_UDP_CLIENT_PORT
DHCP_TIMEOUT
DHCP_RETRIES

67
68

//UDP port where DHCP requests should be sent


//UDP port clients will receive DHCP replies

10
3

By gi ta m file source v bt u vit code:


Trc ht ta khai bo cc bin s dng :
Code:
//-------------------------------------------------------------------------------------unsigned long DhcpServerIP;
unsigned long DhcpTransactID;
unsigned long DhcpLeaseTime;
unsigned char macaddr[6];
//
unsigned char DhcpTimeout;
unsigned char DhcpRetries;
Vit hm khi to giao thc DHCP:
Code:
//-------------------------------------------------------------------------------------//Ham khoi tao cac thong so ban dau cho DHCP
void dhcpInit(void)
{
ethGetMacAddress(macaddr);
DhcpTransactID = *((unsigned long*)&macaddr[0]);
DhcpLeaseTime = 0;
DhcpTimeout = 1;
DhcpRetries = DHCP_RETRIES;
}
Hm ghi gi tr vo trng option ca DHCP, mi trng option s bt u bng 1 byte option code, tip n l 1 byte
chiu di ca gi tr option, theo sau l cc byte gi tr ca option:
Code:
//-------------------------------------------------------------------------------------//Ham set cac option cua DHCP
unsigned char* dhcpSetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void*
optvalptr)
{
*options++ = optcode;
*options++ = optlen;
while(optlen--)
{
*options++ = *(unsigned char*)optvalptr++;
}
*options = DHCP_OPT_END;
return options;

}
Hm c gi tr t trng option vo 1 bin:
Code:
//-------------------------------------------------------------------------------------//Ham lay cac option cua DHCP
unsigned char dhcpGetOption(unsigned char* options, unsigned char optcode, unsigned char optlen, void*
optvalptr)
{
unsigned char i;
for (;;)
{
if(*options == DHCP_OPT_PAD)
options++;
else if(*options == DHCP_OPT_END)
break;
else if(*options == optcode)
{
optlen = ((optlen<*(options+1))?(optlen):(*(options+1)));
for(i=0; i<optlen; i++)
*(((uint8_t*)optvalptr)+i) = *(options+i+2);
return *(options+1);
}
else
{
options++;
options+=*options;
options++;
}
}
return 0;
}
Hm xut ra cng serial Header ca bn tin (dng cho mc ch debug) :
Code:
//-------------------------------------------------------------------------------------#ifdef DHCP_DEBUG
//Ham de in Header goi DHCP (de debug)
void dhcpPrintHeader(struct netDhcpHeader* packet)
{
printf("DHCP Packet:\r\n");
// print op
printf("Op
: ");
switch(packet->bootp.opcode)
{
case BOOTP_OP_BOOTREQUEST:
printf("BOOTREQUEST"); break;
case BOOTP_OP_BOOTREPLY: printf("BOOTREPLY"); break;
default:
printf("UNKNOWN"); break;
}
printf("\n\r");
// print transaction ID
printf("XID
: 0x"); /*rprintfu32(packet->bootp.transid);*/
printf("\n\r");
// print client IP address
printf("ClIpAddr: ");
ipPrintAddr(HTONL(packet->bootp.clipaddr));
printf("\n\r");
// print 'your' IP address
printf("YrIpAddr: ");
ipPrintAddr(HTONL(packet->bootp.yoipaddr));
printf("\n\r");
// print server IP address
printf("SvIpAddr: ");
ipPrintAddr(HTONL(packet->bootp.seipaddr));
printf("\n\r");
// print gateway IP address
printf("GwIpAddr: ");
ipPrintAddr(HTONL(packet->bootp.gwipaddr));
printf("\n\r");
// print client hardware address
printf("ClHwAddr: ");
ethPrintAddr((struct ntEthAddr*)packet->bootp.clhwaddr);
printf("\n\r");
}
#endif
Hm gi i bn tin DHCP discover :
Code:
//--------------------------------------------------------------------------------------

//Ham gui di mot ban tin DHCP discover de tim kiem DHCP server
void dhcpDiscover(void)
{
struct netDhcpHeader* packet;
unsigned long val;
unsigned char* optptr;
packet = (struct netDhcpHeader*)(ethGetBuffer() + ETH_HEADER_LEN + IP_HEADER_LEN +
UDP_HEADER_LEN);
//
packet->bootp.opcode = BOOTP_OP_BOOTREQUEST;
packet->bootp.hwaddrtype = BOOTP_HTYPE_ETHERNET;
packet->bootp.hwaddrlen = BOOTP_HLEN_ETHERNET;
packet->bootp.clipaddr = HTONL(ipGetConfig()->ip);
packet->bootp.yoipaddr = HTONL(0l);
packet->bootp.seipaddr = HTONL(0l);
packet->bootp.gwipaddr = HTONL(0l);
ethGetMacAddress(&packet->bootp.clhwaddr[0]);
packet->bootp.transid = DhcpTransactID;
packet->bootp.flags = HTONS(1);
//
packet->cookie = 0x63538263;
val = DHCP_MSG_DHCPDISCOVER;
optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
dhcpSetOption(optptr, DHCP_OPT_CLIENTID, 6, macaddr);
#ifdef DHCP_DEBUG
printf("DHCP: Sending Query\r\n");
dhcpPrintHeader(packet);
#endif
udpSend(0xFFFFFFFF, DHCP_UDP_SERVER_PORT, DHCP_UDP_CLIENT_PORT, DHCP_HEADER_LEN+3+1+8,
(unsigned char*)packet);
}
Hm gi bn tin DHCP request p ng li cho DHCP offer :
Code:
//-------------------------------------------------------------------------------------//Ham gui di mot ban tin DHCP request de yeu cau nhan dia chi IP
void dhcpRequest(struct netDhcpHeader* packet, unsigned long serverid)
{
unsigned char* optptr;
unsigned long val;
packet->bootp.opcode = BOOTP_OP_BOOTREQUEST;
// request type
val = DHCP_MSG_DHCPREQUEST;
optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
optptr = dhcpSetOption(optptr, DHCP_OPT_CLIENTID, 6, macaddr);
optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &serverid);
optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.yoipaddr);
((unsigned char*)&val)[0] = DHCP_OPT_NETMASK;
((unsigned char*)&val)[1] = DHCP_OPT_ROUTERS;
((unsigned char*)&val)[2] = DHCP_OPT_DNSSERVERS;
((unsigned char*)&val)[3] = DHCP_OPT_DOMAINNAME;
optptr = dhcpSetOption(optptr, DHCP_OPT_PARAMREQLIST, 4, &val);
packet->bootp.yoipaddr = HTONL(0l);
#ifdef DHCP_DEBUG
printf("DHCP: Sending request in response to offer\r\n");
#endif
udpSend(0xFFFFFFFF, DHCP_UDP_SERVER_PORT, DHCP_UDP_CLIENT_PORT, DHCP_HEADER_LEN+3+6+6+6+8+1,
(unsigned char*)packet);
}
Hm x l gi DHCP nhn c, hm ny s c gi bi giao thc UDP:
Code:
//-------------------------------------------------------------------------------------//Ham xu ly mot goi DHCP nhan duoc
void dhcpIn(unsigned int len, struct netDhcpHeader* packet)
{
unsigned char msgtype;
unsigned long sid;
unsigned long netmask;
unsigned long gateway;

unsigned long val;


//
#ifdef DHCP_DEBUG
dhcpPrintHeader(packet);
#endif
//
if((packet->bootp.opcode != BOOTP_OP_BOOTREPLY) || (packet->bootp.transid != DhcpTransactID))
return;
//
dhcpGetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &msgtype);
#ifdef DHCP_DEBUG
printf("DHCP: Received msgtype = %d\r\n", msgtype);
#endif
//
if(msgtype == DHCP_MSG_DHCPOFFER)
{
dhcpGetOption(packet->options, DHCP_OPT_SERVERID, 4, &sid);
#ifdef DHCP_DEBUG
printf("DHCP: Got offer from server "); ipPrintAddr(HTONL(sid)); printf("\n\r");
#endif
dhcpRequest(packet, sid);
}
//
else if(msgtype == DHCP_MSG_DHCPACK)
{
dhcpGetOption(packet->options, DHCP_OPT_NETMASK, 4, &val);
netmask = HTONL(val);
//
dhcpGetOption(packet->options, DHCP_OPT_ROUTERS, 4, &val);
gateway = HTONL(val);
//
dhcpGetOption(packet->options, DHCP_OPT_LEASETIME, 4, &val);
DhcpLeaseTime = HTONL(val);
//
ipSetConfig(HTONL(packet->bootp.yoipaddr), netmask, gateway);
//
DhcpRetries = 0;
#ifdef DHCP_DEBUG
printf("DHCP: Got request ACK, bind complete\r\n");
ipPrintConfig(ipGetConfig());
printf("LeaseTm : %d\n\r", DhcpLeaseTime);
#endif
}
}
Hm hy b a ch IP hin ti:
Code:
//-------------------------------------------------------------------------------------//Ham release dia chi IP hien tai va xoa cac thong so cau hinh IP dang co
void dhcpRelease(void)
{
struct netDhcpHeader* packet;
unsigned long val;
unsigned char* optptr;
//
packet = (struct netDhcpHeader*)&ethGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
//
packet->bootp.opcode = BOOTP_OP_BOOTREQUEST;
packet->bootp.hwaddrtype = BOOTP_HTYPE_ETHERNET;
packet->bootp.hwaddrlen = BOOTP_HLEN_ETHERNET;
packet->bootp.clipaddr = HTONL(ipGetConfig()->ip);
packet->bootp.yoipaddr = HTONL(0l);
packet->bootp.seipaddr = HTONL(0l);
packet->bootp.gwipaddr = HTONL(0l);
ethGetMacAddress(&packet->bootp.clhwaddr[0]);
packet->bootp.transid = DhcpTransactID;
packet->bootp.flags = HTONS(1);
//
packet->cookie = 0x63538263;
//
val = DHCP_MSG_DHCPRELEASE;
optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
//

val = HTONL(DhcpServerIP);
optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &val);
//
optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.clipaddr);
//
#ifdef DHCP_DEBUG
printf("DHCP: Sending Release to "); ipPrintAddr(DhcpServerIP); printf("\n\r");
#endif
udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_UDP_CLIENT_PORT, DHCP_HEADER_LEN+3+6+6+1,
(unsigned char*)packet);
ipSetConfig(0,0,0);
DhcpLeaseTime = 0;
}
Hm cp nht cc bin thi gian m DHCP s dng (c gi 1s/ln bi timer):
Code:
//-------------------------------------------------------------------------------------//Ham duoc goi dinh ky moi 1s de cap nhat lease time va timeout cua DHCP
void dhcpTimer(void)
{
// this function to be called once per second
// decrement lease time
if(DhcpLeaseTime)
DhcpLeaseTime--;
if(DhcpTimeout){
DhcpTimeout--;
}
}
Hm dch v DHCP, ta s a vo vng lp chng trnh chnh:
Code:
//-------------------------------------------------------------------------------------//Ham dich vu DHCP, duoc goi trong chuong trinh chinh
void dhcpService(void)
{
if(DhcpRetries && (DhcpTimeout == 0)){
DhcpRetries--;
DhcpTimeout = DHCP_TIMEOUT;
dhcpDiscover();
}
}
//-------------------------------------------------------------------------------------Vy l xong file source v header cho DHCP, cc bn nh thm khai bo hm vo file header nh

Tip theo, c th chy th giao thc DHCP, chng ta cn modify source c mt t b sung giao thc ny vo:
1-M file timer.h sa define cho prescale ca timer thnh 1024 timer chy ng, ngt 1s/ln (vi thch anh 12MHz
nha cc bn):
Code:
#define TIMER1PRESCALE

TIMER_CLK_DIV1024

2-M file udp.c, sa hm udpSend b sung source port vo trong hm, thm lnh gi hm ca giao thc DHCP vo
hm UDPProcess:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ip.h"
#include "uart.h"
#include "dhcp.h"
//#define UDP_DEBUG
//---------------------------------------------------------------------------//Ham gui di mot goi UDP
void udpSend(unsigned long dstIp, unsigned int dstPort, unsigned int srcPort, unsigned int len,
unsigned char* udpData)
{

struct ntUDPHeader* udpHeader;


udpHeader = (struct ntUDPHeader*)(udpData - UDP_HEADER_LEN);
len += UDP_HEADER_LEN;
udpHeader->desPort = HTONS(dstPort);
udpHeader->srcPort = HTONS(srcPort);
udpHeader->Len = HTONS(len);
udpHeader->Checksum = 0;
ipSend(dstIp, IP_PROTO_UDP, len, (unsigned char*)udpHeader);
}
//-------------------------------------------------------------------------------------//Ham xu ly goi UDP nhan duoc, duoc goi boi ham xu ly goi IP (IPProcess)
// Hien chua co ung dung chay UDP nen ham nay trong
void UDPProcess(unsigned int len, struct ntIPHeader* packet)
{
dhcpIn((len - IP_HEADER_LEN - UDP_HEADER_LEN), (struct netDhcpHeader*)((char*)packet +
IP_HEADER_LEN + UDP_HEADER_LEN));
#ifdef UDP_DEBUG
printf("Rx UDP Packet\r\n");
#endif
}
//-------------------------------------------------------------------------------------(Nh cp nht khai bo hm bn file header nha)
3-Thm mt s include (khi dch bo li th cc bn cng t tm ra m thm vo thi, ch lun cho mc cng kim):
#include <avr/pgmspace.h>//// vo tcp.h
#include "dhcp.h"//// vo ntAVRnet.h
#include "udp.h" v #include "icmp.h" vo ip.h
4-Sa hm IPProcess, thm cc lnh gi hm ca giao thc UDP, TCP vo:
Code:
void IPProcess(unsigned int len, struct ntIPHeader* packet)
{
// check IP addressing, stop processing if not for me and not a broadcast
if( (HTONL(packet->desIPAddr) != ipGetConfig()->ip) &&
(HTONL(packet->desIPAddr) != (ipGetConfig()->ip|ipGetConfig()->netmask)) &&
(HTONL(packet->desIPAddr) != 0xFFFFFFFF) &&
(ipGetConfig()->ip != 0x00000000) )
return;
// handle ICMP packet
if( packet->Protocol == IP_PROTO_ICMP )
{
#ifdef IP_DEBUG
printf("IP->Rx: ICMP/IP packet\r\n");
//icmpPrintHeader((icmpip_hdr*)packet);
#endif
icmpIpIn((struct ntIPHeader*)packet);
}
else if( packet->Protocol == IP_PROTO_UDP )
{
#ifdef IP_DEBUG
printf("IP->Rx: UDP/IP packet\r\n");
//debugPrintHexTable(NetBufferLen-14, &NetBuffer[14]);
#endif
UDPProcess(len, ((struct ntIPHeader*)packet) );////
}
else if( packet->Protocol == IP_PROTO_TCP )
{
#ifdef IP_DEBUG
printf("IP->Rx: TCP/IP packet\r\n");
#endif
TCPProcess((unsigned char *)packet,len-((packet->verHdrLen & 0x0F)<<2));////
}
else
{
#ifdef IP_DEBUG
printf("IP->Rx: IP packet\r\n");
#endif
}
}
//--------------------------------------------------------------------------------------

5-M hm ngt timer 1 (trong file timer.h), thm vo cc hm cp nht thi gian ca giao thc TCP v DHCP vo:
Code:
TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
{
//Tai nap gia tri timer 1
TCNT1 = 0xFFFF - TIMER1_INTERVAL;
//Cap nhat watchdog timer
if((time_watchdog++) > 120){
time_watchdog = 0;
ethInit();
}
Counter1s++;
arpTimer();
TCPCheckTimeOut();////
dhcpTimer();////
}
6-Thm vo hm main trong file ntAVRnet.h
Code:
int
{

main()
SystemInit();
printf("\r\nNTTam AVR network testing with enc28j60.\r\n");
printf("Initializing Network Interface and Stack\r\n");
printf("Ethernet chip init\r\n");
IpMyConfig.ethaddr.addr[0] = ETHADDR0;
IpMyConfig.ethaddr.addr[1] = ETHADDR1;
IpMyConfig.ethaddr.addr[2] = ETHADDR2;
IpMyConfig.ethaddr.addr[3] = ETHADDR3;
IpMyConfig.ethaddr.addr[4] = ETHADDR4;
IpMyConfig.ethaddr.addr[5] = ETHADDR5;
IpMyConfig.ip = IPADDRESS;
IpMyConfig.netmask = NETMASK;
IpMyConfig.gateway = GATEWAY;
netInit(IpMyConfig.ip, IpMyConfig.netmask, IpMyConfig.gateway);
PrintIPConfig();
printf("Getting IP Address....\r\n");
if(IpMyConfig.ip == 0x00000000){
dhcpInit();
}
while(1)
{
ethService();
dhcpService();
}
return 0;

}
By gi nu lc u mch ca ta cha c a ch IP (IP address l 0.0.0.0) th n s khi to giao thc DHCP nhn a
ch IP.
th, ta chnh li cc thng s cu hnh IP trong file ntAVRnet.h nh sau:
Code:
#define IPDOT(a,b,c,d)
((unsigned long)((unsigned char)a)<<24)+((unsigned long)((unsigned
char)b)<<16)+((unsigned long)((unsigned char)c)<<8)+(unsigned char)d//((a<<24)|(b<<16)|(c<<8)|(d))
//#define IPADDRESS
IPDOT(192,168,1,10)
#define IPADDRESS
IPDOT(0,0,0,0)
#define NETMASK
IPDOT(0,0,0,0)
#define GATEWAY
IPDOT(0,0,0,0)
By gi ta c th bin dch, ni cp mng v m ngun, i board nhn a ch IP (nh kt ni cng COM cn bit n
nhn c a ch bao nhiu nh).
Phn code ny ch khi ng DHCP lc mi reset mch thi nh, cha h tr hot plug cp mng
sa code thm phn ny vo.

. Cc bn c th t

Nguyn vn bi tienhuypro
Cho em hi thm l:
1- Khi gi tin c gi ra khi modem ADSL n router bin th lc ny cc router ch cn da vo bng nh tuyn m chuyn tip d liu

hay l c cn thm a ch MAC g khng.


2- IP WAN 123.20.165.7 c ngh a g trong qu trnh gi data khng.
3- Khi mt my tnh trn internet mun truy cp vo mch AVRnet ca mnh th ph i g //ip l bao nhiu vy.
1-Tt c cc router, khng ring g router bin, li hay router khch hng, u ch da vo bng nh tuyn chuyn d
liu i, router khng quan tm n a ch MAC. Chnh v vy router c xem l thit b lp 3 (lp network).
2-C mt iu cn lu l a ch IP 192.168.1.x ch l a ch local cho mng LAN, bn ngoi ch bit ti chng ta qua
a ch IP WAN, khi gi tin ra mng internet, nu trong trng Source IP Address vn a ch ny, th my tnh trn
mng Internet khi tr li s tr li theo a ch ny th s khng ti c router ADSL ca chng ta. Vi vy trc khi
Router ADSL chuyn gi tin i ra mng WAN, n s thay a ch Source IP Address trong header IP bng a ch IP WAN
ca n (123.20.165.7). Nh vy khi my tnh trn Internet nhn c v tr li theo a ch ny, Router ADSL s nhn
c, trc khi chuyn gi tin vo bn trong mng LAN, n thay tr li bng a ch Local (192.168.1.x). Hot ng ny
gi l NAT (Network Address Translate) m bn ding_dong c ln nhc ti nhng ti cha c dp ni chi tit.
3-T Internet, mun truy cp vo mch ca chng ta tt nhin phi truy cp ti a ch IP WAN (g http://123.20.165.7).
Khi trong modem ADSL ta cn khai bo n chuyn mi truy cp HTTP ti a ch IP WAN sang cho mch AVRnet (
chnh l phn cu hnh modem, s hng dn cui cng).
Bi 7: Giao thc HTTP
- HTTP l ch vit tt t HyperText Transfer Protocol (giao thc truyn ti siu vn bn). N l giao thc c bn m World
Wide Web s dng truyn ti ni dung cc trang web. HTTP xc nh cch cc thng ip (cc file vn bn, hnh nh
ho, m thanh, video, v cc file multimedia khc c nh dng v truyn ti ra sao, v hot ng ca Web server
v cc trnh duyt Web.
- Trong m hnh ca HTTP, Webserver ng thi cng l TCP server, m sn port mc nh dnh cho dch v HTTP l
TCP80 ( ch listen), sn sng i yu cu kt ni t cc client.
- Cc client s khi to kt ni TCP thng qua port ny, sau khi Webserver chp nhn kt ni, client s gi mt bn tin
HTTP (HTTP message) gi l HTTP request ti server trn kt ni TCP va thit lp.
- Server s tr li li bng mt bn tin HTTP khc l HTTP response. Bn tin ny s cha ni dung trang Web yu cu
(c vit bng ngn ng HTML).
Nh vy giao thc HTTP s da c bn trn cc bn tin HTTP, gm 2 loi l HTTP request v HTTP response.
Gi s ngi dng truy cp URL: www.dientuvietnam.net/index.html (trang web c text v 10 hnh nh jpeg):
1a-HTTP client thit lp lin kt TCP vi HTTP server (process) ti a ch www.dientuvietnam.net, cng 80 (ngm nh
cho dch v HTTP).
1b-HTTP server ti my ch www.dientuvietnam.net ch yu cu kt ni TCP ti cng 80, chp nhn kt ni ri thng bo
vi client.
2-HTTP client gi HTTP request message (bao gm c URL) ti TCP connection socket.
3-HTTP server nhn request message, to ra HTTP response message c cha cc i tng c yu cu ri gi vo
socket.
4-HTTP server ngt lin kt.
5-HTTP client nhn response message c cha file html, hin th html. Sau , phn tch file html, tm URL ca 10 hnh
nh jpeg trong ti liu.
6-Bc 1-5 c lp li vi tng hnh nh.
C nhiu phin bn HTTP, tuy nhin y chng ta s bt u vi phin bn HTTP n gin nht: HTTP 1.0
1-Cu trc cc bn tin HTTP:
Bn tin HTTP (HTTP message) gm 2 loi: HTTP request v HTTP response. i vi HTTP request ta c Simple-Request v
Full-Request. Tng t ta cng c Simple-Response v Full-Response.

1.1-Bn tin HTTP request:

a-Simple-Request: c cu trc rt n gin


GET<space><Request-URI><CRLF>
b-Full-Request: c cu trc tng qut gm c 3 phn nh sau
[Request-Line]
[Headers]
<CRLF>
[Entity-Body]
Request-Line: c c php nh sau:
<Method><space><Request-URI><space><HTTP-Version><CRLF>
Trong :
- Method l tn phng thc HTTP, vi HTTP 1.0 ta c cc method chnh l: "GET", "HEAD" v "POST".
- Request-URI l ng dn ti trang web cn ti, c th l ng dn tng i hay tuyt i.
- HTTP-Version: cho bit phin bn HTTP ang s dng.
V d:
- Request line vi URI tuyt i:
GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.0
- Request line vi URI tng i:
GET /pub/WWW/TheProject.html HTTP/1.0
Headers: c 3 loi: General-Header; Request-Header; Entity-Header
C nhiu Header khc nhau trong mi loi, y khng tin trnh by ht, nhng nhn chung, HTTP Header c c php
nh sau:
<field-name>: <field-value> <CRLF>
Entity-Body: cha cc thng tin km theo request (v d khi ta nhn nt Submit trn 1 trang web s dng phng
thc HTTP POST, trng thi ca cc nt check, gi tr trong cc edit text,... s c cha trong phn ny.
V d:
- Mt bn tin HTTP request dng phng thc GET:
GET /path/file.html HTTP/1.0<CRLF>
From: someuser@jmarshall.com<CRLF>
User-Agent: HTTPTool/1.0<CRLF>
<CRLF>
Trong phng thc GET ny, phn body l trng (khng c message body)
- Mt bn tin HTTP request dng phng thc POST:
POST /path/script.cgi HTTP/1.0<CRLF>
From: frog@jmarshall.com<CRLF>
User-Agent: HTTPTool/1.0<CRLF>
Content-Type: application/x-www-form-urlencoded<CRLF>
Content-Length: 32<CRLF>
<CRLF>
home=Cosby&favorite+flavor=flies
Dng
Dng
Dng
Dng

1 l request line
2,3,4,5 l cc header
6 ch cha 1 k t xung dng (<CRLF>) bo ht phn Header, bt u mesage body
7 chnh l phn body

y chng ta cn lu l di Headers khng c nh, nhng kt thc bng <CRLF>. Do khi vit chng trnh cho
AVR, ta s tm ch no c 2 k t <CRLF> lin tip th l kt thc Headers.

1.1-Bn tin HTTP response:

a-Simple-Response: c cu trc rt n gin, ch cha phn Entity-Body


[Entity-Body]
b-Full-Response: c cu trc tng qut gm c 3 phn nh sau
<Status-Line>
<Headers>
<CRLF>
[Entity-Body]
Status-Line: c c php nh sau
<HTTP-Version><space><Status-Code><Space><Reason-Phrase><CRLF>
Trong :
- HTTP-Version: cho bit phin bn giao thc HTTP. V d: "HTTP/1.0"
- Status-Code: cho bit m trng thi ca response. Gm 3 ch s, c qui nh nh sau
+ 1xx: Informational - cha c s dung, d phng
+ 2xx: Thnh cng (Success) - cho bit request c chp nhn v p ng.
+ 3xx: Chuyn hng (Redirection) - yu cu client chuyn hng request
+ 4xx: Li do client (Client Error) - request khng hp l
+ 5xx: Li do sever (Server Error) - request hp l nhng server b li khng th tr li
Cc Status-Code c th hay dng:
+ "200" ; OK
+ "201" ; Created
+ "202" ; Accepted
+ "204" ; No Content
+ "301" ; Moved Permanently
+ "302" ; Moved Temporarily
+ "304" ; Not Modified
+ "400" ; Bad Request
+ "401" ; Unauthorized
+ "403" ; Forbidden
+ "404" ; Not Found
+ "500" ; Internal Server Error
+ "501" ; Not Implemented
+ "502" ; Bad Gateway
+ "503" ; Service Unavailable
- Reason-Phrase: cha ni dung text gii thch cho response.
Headers: c php tng t header ca request, cng gm General-Header; Response-Header; Entity-Header
Entity-Body:cha phn ni dung tr li ca response (v du ni dung file html)
V d: Mt response cho phng thc GET
HTTP/1.0 200 OK<CRLF>
Date: Fri, 31 Dec 1999 23:59:59 GMT<CRLF>
Content-Type: text/html<CRLF>
Content-Length: 1354<CRLF>
<CRLF>

<html>
<body>
<h1>Happy New Millennium!</h1>
(more file contents)
.
.
.
</body>
</html>
Dng
Dng
Dng
Dng
Dng

1: Status-Line
2: General Header
3,4: Entity-Header
5: <CRLF>, bo hiu kt thc headers
6 tr i: Entity body

Ngn ng HTML v thit k web cho AVR webserver:


Phn ny khng bit phi trnh by sao na, v gii thch v HTML v thit k web th di dng qu, nn ch hng dn
cc bn lm 1 trang web n gin nhng vo AVR thi.
u tin ta dng bt c 1 phn mm c h tr thit k web no cng c, microsoft ofice word, microsoft ofice
frontpage, ofice publisher, ... (mnh dng Adobe Dreamweaver CS5 do sn tin ang dng vit PHP) thit k 1
trang web n gin tng t nh sau:

Bn no cha bit lm hoc li c th lm nh sau:


1-M notepad.
2-Copy code html sau vo:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AVR web server</title>
</head>
<body style="background: #048C04; color: #FFFFFF">

<br>
<table bgcolor="#489D48" border="0" width="975" cellpadding="0" cellspacing="0" align="center">
<tbody>
<tr>
<td height="31" align="center">
<div style="font-size:48pt; color:#F4FC8F"><strong>REMOTE CONTROL AVR WEBSERVER</strong></div>
</td>
</tr>
</tbody>
</table>
<table width="100%" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<br>
<div align="center">
<div style="background: #ffffff; color: #000000; width:975px; text-align:left">
<div style="padding:0px 15px 0px 15px" align="left">
<br>
<table style="background: #999999; color: #000000; border: 1px solid #6581c1" cellpadding="6"
cellspacing="1" border="0" width="100%" align="center">
<tbody>
<tr style="background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top:
1px solid #FFFFFF">
<td width="100%">
<div style="font-size:10pt"><strong>DESIGNER: THANH - TAM</strong></div>
</td>
<td nowrap="nowrap" style="padding:0px">
</td>
</tr>
</tbody>
</table>
<br>
<table style="background: #999999; color: #000000; border: 1px solid #6581c1" cellpadding="6"
cellspacing="1" border="0" width="100%" align="center">
<thead>
<tr valign="top">
<td style="background: #FFFFFF; color: #048C04" colspan="3"><strong>Remote control webserver
with ATmega32</a></strong></td>
</tr>
</thead>
<tbody id="collapseobj_vietvbb_stats" style="">
<tr>
<td style="background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top:
1px solid #FFFFFF">
<table border="1" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr style="font-size:12pt">
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div>
<strong>Camera view</strong>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div>
<strong>Devices control</strong>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="50%">
<div>
<strong>Sensors</strong>
</div>
</td>
</tr>
<tr style="font:bold 12pt">
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div id="vietvbb_topstats_s_content" style="display: block;">
<img
src="http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg"
width="320" height="240" />
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="25%">

<div>
<form method="POST" action="">
<p align="left"><input type="checkbox" name="RELAY1" value="ON"%RL1>Relay
<p align="left"><input type="checkbox" name="RELAY2" value="ON"%RL2>Relay
<p align="left"><input type="checkbox" name="RELAY3" value="ON"%RL3>Relay
<p align="left"><input type="checkbox" name="RELAY4" value="ON"%RL4>Relay
<p align="left"><input type="submit" value="Submit" name="CTRL"></p>
</form>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="50%">
<div>

01</p>
02</p>
03</p>
04</p>

<table border="1" width="100%" id="table1">


<tr>
<td>Environment Sensors</td>
<td width="42">Value</td>
<td width="33">Unit</td>
<td width="150">&nbsp;</td>
</tr>
<tr>
<td>Sensor 01</td>
<td width="42">%AD0</td>
<td width="33"><sup>o</sup>C</td>
<td width="150">&nbsp;</td>
</tr>
<tr>
<td>Sensor 02</td>
<td width="42">%AD1</td>
<td width="33"><sup>o</sup>C</td>
<td width="150">&nbsp;</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<br><br><br>
<div align="center">Timezone: GMT+7. Current time <span>%TI</span>.</div>
<br>
</div>
</div>
</div>
<form action="footer" method="get">
<br>
<div align="center">
<div align="center">Designed by thanh - tam</div>
</div>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
3-Chn Save as: Chn Save as type: All file; Encoding: UTF-8; t tn file l web.html (nh ng ui nh).
4-Dng trnh duyt m xem th.
5-Dng Microsoft Office word hay bt c phn mm son tho web no edit li theo mnh.
on code trn chnh l m HTML m t ni dung trang web m webserver phi tr li li cho 1 bn tin HTTP request
(GET hay POST)
Trong trang web trn ta c 1 hnh nh (ch cn nh mnh) nhng ta khng lu hnh nh ny trn ROM m upload trn 1
server khc ri nhng code vo thi, tit kim b nh cho AVR.

Nh vy kch bn truy cp vo webserver vi trang web trn nh sau (gi s ta ch mi truy cp trong mng LAN vi IP
ca mch l 192.168.1.10):

1-Webserver (mch AVR+ENC28J60) m sn cng TCP 80 (listen) i nhn kt ni t client.


2-Ta m trnh duyt, g a ch http://192.168.1.10
3-My tnh khi to 1 kt ni TCP ti a ch IP 192.168.1.10, port ch l 80, port ngun do n t chn (gi bn tin SYN).
4-Webserver chp nhn kt ni (tr li bn tin SYN), client xc nhn ACK (xem li phn giao thc TCP). Kt ni TCP c
thit lp.
5-Client gi bn tin HTTP request vi phng thc GET. Ni dung nh sau (v d):
Code:
GET http://192.168.1.10/index.html HTTP/1.0<CRLF>
User-Agent: Chrome/15.0<CRLF>
<CRLF>
6-Webserver tr li bng mt bn tin HTTP response, vi phn Entity-body chnh l ni dung m HTML ca trang web
trn:
Code:
HTTP/1.0 200 Document follows<CRLF>
Server: AVR_Small_Webserver<CRLF>
Content-Type: text/html<CRLF>
Content-Length: 1234<CRLF>
<CRLF>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AVR web server</title>
</head>
<body style="background: #048C04; color: #FFFFFF">
<br>
<table bgcolor="#489D48" border="0" width="975" cellpadding="0" cellspacing="0" align="center">
<tbody>
<tr>
<td height="31" align="center">
<div style="font-size:48pt; color:#F4FC8F"><strong>REMOTE CONTROL AVR WEBSERVER</strong></div>
</td>
</tr>
</tbody>
</table>
<table width="100%" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<br>
<div align="center">
<div style="background: #ffffff; color: #000000; width:975px; text-align:left">
<div style="padding:0px 15px 0px 15px" align="left">
<br>
<table style="background: #999999; color: #000000; border: 1px solid #6581c1" cellpadding="6"
cellspacing="1" border="0" width="100%" align="center">
<tbody>
<tr style="background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top:
1px solid #FFFFFF">
<td width="100%">
<div style="font-size:10pt"><strong>DESIGNER: THANH - TAM</strong></div>
</td>
<td nowrap="nowrap" style="padding:0px">
</td>
</tr>
</tbody>
</table>
<br>

<table style="background: #999999; color: #000000; border: 1px solid #6581c1" cellpadding="6"
cellspacing="1" border="0" width="100%" align="center">
<thead>
<tr valign="top">
<td style="background: #FFFFFF; color: #048C04" colspan="3"><strong>Remote control webserver
with ATmega32</a></strong></td>
</tr>
</thead>
<tbody id="collapseobj_vietvbb_stats" style="">
<tr>
<td style="background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top:
1px solid #FFFFFF">
<table border="1" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr style="font-size:12pt">
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div>
<strong>Camera view</strong>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div>
<strong>Devices control</strong>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="50%">
<div>
<strong>Sensors</strong>
</div>
</td>
</tr>
<tr style="font:bold 12pt">
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div id="vietvbb_topstats_s_content" style="display: block;">
<img
src="http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg"
width="320" height="240" />
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="25%">
<div>
<form method="POST" action="">
<p align="left"><input type="checkbox" name="RELAY1" value="ON"%RL1>Relay 01</p>
<p align="left"><input type="checkbox" name="RELAY2" value="ON"%RL2>Relay 02</p>
<p align="left"><input type="checkbox" name="RELAY3" value="ON"%RL3>Relay 03</p>
<p align="left"><input type="checkbox" name="RELAY4" value="ON"%RL4>Relay 04</p>
<p align="left"><input type="submit" value="Submit" name="CTRL"></p>
</form>
</div>
</td>
<td style="padding: 5px 5px 5px 5px;" width="50%">
<div>
<table border="1" width="100%" id="table1">
<tr>
<td>Environment Sensors</td>
<td width="42">Value</td>
<td width="33">Unit</td>
<td width="150">&nbsp;</td>
</tr>
<tr>
<td>Sensor 01</td>
<td width="42">%AD0</td>
<td width="33"><sup>o</sup>C</td>
<td width="150">&nbsp;</td>
</tr>
<tr>
<td>Sensor 02</td>
<td width="42">%AD1</td>
<td width="33"><sup>o</sup>C</td>
<td width="150">&nbsp;</td>
</tr>
</table>
</div>

</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<br><br><br>
<div align="center">Timezone: GMT+7. Current time <span>%TI</span>.</div>
<br>
</div>
</div>
</div>
<form action="footer" method="get">
<br>
<div align="center">
<div align="center">Designed by thanh - tam</div>
</div>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
7-Webserver ng kt ni TCP.
8-Trnh duyt trn client phn tch m HTML, hin th ni dung trang web, phn hnh nh (<img
src="http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg" width="320"
height="240" />) vn cha c (cha trng).
9-Client cn c vo URL ca hnh nh
(http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg) thit lp 1 kt ni TCP
mi, ti hnh nh trn v v hin th ln.
i ngi c g thc mc c hi nh. i ch c l gii thch khng c r rng lm.
By gi bt u phn Coding:
Tng t, ta to ra cc file source v header trong project:
File "http.c"
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#include "packet.h"
#include "ethernet.h"
#include "http.h"
#include "webpage.h"
#include "uart.h"
#include "ntAVRnet.h"
File "http.h"
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef HTTP_H
#define HTTP_H

//---------------------------------------------------------------------------#endif //HTTP_H
Ta to thm 1 file header c tn "webpage.h" cha ni dung trang web

Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef WEBPAGE_H
#define WEBPAGE_H

//---------------------------------------------------------------------------#endif //WEBPAGE_H
By gi ta bt u vi file "webpage.h" trc, chuyn ni dung file HTML m ta son tho phn trc vo trong ROM
ca AVR:
Ta khai bo trong "webpage.h" mt chui k t lu trong b nh ROM:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef WEBPAGE_H
#define WEBPAGE_H
//
#include <avr/pgmspace.h>
PROGMEM char Page1[] = {};
//---------------------------------------------------------------------------#endif //WEBPAGE_H
Tip theo ta chuyn ni dung file html trn vo chui trn. Lm theo cc bc sau:
1-M notepad, copy tt c m html trong file "web.html" chun b vo. C th b cc k t <space> u dng cho
tit kim b nh.
2-Bm Ctrl-H m cng c find & replace: tm k t du nhy kp: " v thay tt c bng: \". L do ca thao tc ny l
trong ngn ng C, du nhy kp s kt thc 1 chui, do nu trong chui ca ta c du nhy ny th phi thay bng \" .
Kt qu ti y ta s c ni dung trn notepad nh sau:
Code:
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"en\">
<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">
<title>AVR web server</title>
</head>
<body style=\"background: #048C04; color: #FFFFFF\">
<br>
<table bgcolor=\"#489D48\" border=\"0\" width=\"975\" cellpadding=\"0\" cellspacing=\"0\"
align=\"center\">
<tbody>
<tr>
<td height=\"31\" align=\"center\">
<div style=\"font-size:48pt; color:#F4FC8F\"><strong>REMOTE CONTROL AVR WEBSERVER</strong></div>
</td>
</tr>
</tbody>
</table>
<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">
<tbody>
<tr>
<td>
<br>
<div align=\"center\">
<div style=\"background: #ffffff; color: #000000; width:975px; text-align:left\">
<div style=\"padding:0px 15px 0px 15px\" align=\"left\">
<br>
<table style=\"background: #999999; color: #000000; border: 1px solid #6581c1\" cellpadding=\"6\"
cellspacing=\"1\" border=\"0\" width=\"100%\" align=\"center\">
<tbody>
<tr style=\"background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top: 1px solid
#FFFFFF\">

<td width=\"100%\">
<div style=\"font-size:10pt\"><strong>DESIGNER: THANH - TAM</strong></div>
</td>
<td nowrap=\"nowrap\" style=\"padding:0px\">
</td>
</tr>
</tbody>
</table>
<br>
<table style=\"background: #999999; color: #000000; border: 1px solid #6581c1\" cellpadding=\"6\"
cellspacing=\"1\" border=\"0\" width=\"100%\" align=\"center\">
<thead>
<tr valign=\"top\">
<td style=\"background: #FFFFFF; color: #048C04\" colspan=\"3\"><strong>Remote control webserver with
ATmega32</a></strong></td>
</tr>
</thead>
<tbody id=\"collapseobj_vietvbb_stats\" style=\"\">
<tr>
<td style=\"background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top: 1px solid
#FFFFFF\">
<table border=\"1\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">
<tbody>
<tr style=\"font-size:12pt\">
<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">
<div>
<strong>Camera view</strong>
</div>
</td>
<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">
<div>
<strong>Devices control</strong>
</div>
</td>
<td style=\"padding: 5px 5px 5px 5px;\" width=\"50%\">
<div>
<strong>Sensors</strong>
</div>
</td>
</tr>
<tr style=\"font:bold 12pt\">
<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">
<div id=\"vietvbb_topstats_s_content\" style=\"display: block;\">
<img src=\"http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg\"
width=\"320\" height=\"240\" />
</div>
</td>
<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">
<div>
<form method=\"POST\" action=\"\">
<p align=\"left\"><input type=\"checkbox\" name=\"RELAY1\" value=\"ON\"%RL1>Relay 01</p>
<p align=\"left\"><input type=\"checkbox\" name=\"RELAY2\" value=\"ON\"%RL2>Relay 02</p>
<p align=\"left\"><input type=\"checkbox\" name=\"RELAY3\" value=\"ON\"%RL3>Relay 03</p>
<p align=\"left\"><input type=\"checkbox\" name=\"RELAY4\" value=\"ON\"%RL4>Relay 04</p>
<p align=\"left\"><input type=\"submit\" value=\"Submit\" name=\"CTRL\"></p>
</form>
</div>
</td>
<td style=\"padding: 5px 5px 5px 5px;\" width=\"50%\">
<div>
<table border=\"1\" width=\"100%\" id=\"table1\">
<tr>
<td>Environment Sensors</td>
<td width=\"42\">Value</td>
<td width=\"33\">Unit</td>
<td width=\"150\">&nbsp;</td>
</tr>
<tr>
<td>Sensor 01</td>
<td width=\"42\">%AD0</td>
<td width=\"33\"><sup>o</sup>C</td>

<td width=\"150\">&nbsp;</td>
</tr>
<tr>
<td>Sensor 02</td>
<td width=\"42\">%AD1</td>
<td width=\"33\"><sup>o</sup>C</td>
<td width=\"150\">&nbsp;</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<br><br><br>
<div align=\"center\">Timezone: GMT+7. Current time <span>%TI</span>.</div>
<br>
</div>
</div>
</div>
<form action=\"footer\" method=\"get\">
<br>
<div align=\"center\">
<div align=\"center\">Designed by thanh - tam</div>
</div>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
3-Ta thm du nhy kp vo u v cui mi dng.
4-Copy tt c, b vo gia 2 du ngoc nhn trong khai bo PROGMEM char Page1[] = {};
Kt qu ta s c file "webpage.h" nh vy:
Code:
//---------------------------------------------------------------------------// Writen by NTTam - PTITHCM
//---------------------------------------------------------------------------#ifndef WEBPAGE_H
#define WEBPAGE_H
//
#include <avr/pgmspace.h>
PROGMEM char Page1[] = {"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
"<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"en\">"
"<head>"
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
"<title>AVR web server</title>"
"</head>"
"<body style=\"background: #048C04; color: #FFFFFF\">"
"<br>"
"<table bgcolor=\"#489D48\" border=\"0\" width=\"975\" cellpadding=\"0\" cellspacing=\"0\"
align=\"center\">"
"<tbody>"
"<tr>"
"<td height=\"31\" align=\"center\">"
"<div style=\"font-size:48pt; color:#F4FC8F\"><strong>REMOTE CONTROL AVR WEBSERVER</strong></div>"
"</td>"
"</tr>"
"</tbody>"
"</table>"
"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">"

"<tbody>"
"<tr>"
"<td>"
"<br>"
"<div align=\"center\">"
"<div style=\"background: #ffffff; color: #000000; width:975px; text-align:left\">"
"<div style=\"padding:0px 15px 0px 15px\" align=\"left\">"
"<br>"
"<table style=\"background: #999999; color: #000000; border: 1px solid #6581c1\" cellpadding=\"6\"
cellspacing=\"1\" border=\"0\" width=\"100%\" align=\"center\">"
"<tbody>"
"<tr style=\"background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top: 1px solid
#FFFFFF\">"
"<td width=\"100%\">"
"<div style=\"font-size:10pt\"><strong>DESIGNER: THANH - TAM</strong></div>"
"</td>"
"<td nowrap=\"nowrap\" style=\"padding:0px\">"
"</td>"
"</tr>"
"</tbody>"
"</table>"
"<br>"
"<table style=\"background: #999999; color: #000000; border: 1px solid #6581c1\" cellpadding=\"6\"
cellspacing=\"1\" border=\"0\" width=\"100%\" align=\"center\">"
"<thead>"
"<tr valign=\"top\">"
"<td style=\"background: #FFFFFF; color: #048C04\" colspan=\"3\"><strong>Remote control webserver with
ATmega32</a></strong></td>"
"</tr>"
"</thead>"
"<tbody id=\"collapseobj_vietvbb_stats\" style=\"\">"
"<tr>"
"<td style=\"background: #FFFFFF; color: #545454; border-left: 1px solid #FFFFFF; border-top: 1px solid
#FFFFFF\">"
"<table border=\"1\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">"
"<tbody>"
"<tr style=\"font-size:12pt\">"
"<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">"
"<div>"
"<strong>Camera view</strong>"
"</div>"
"</td>"
"<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">"
"<div>"
"<strong>Devices control</strong>"
"</div>"
"</td>"
"<td style=\"padding: 5px 5px 5px 5px;\" width=\"50%\">"
"<div>"
"<strong>Sensors</strong>"
"</div>"
"</td>"
"</tr>"
"<tr style=\"font:bold 12pt\">"
"<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">"
"<div id=\"vietvbb_topstats_s_content\" style=\"display: block;\">"
"<img src=\"http://d.f5.photo.zdn.vn/upload/original/2011/06/19/1/24/1308421475585659804_574_0.jpg\"
width=\"320\" height=\"240\" />"
"</div>"
"</td>"
"<td style=\"padding: 5px 5px 5px 5px;\" width=\"25%\">"
"<div>"
"<form method=\"POST\" action=\"\">"
"<p align=\"left\"><input type=\"checkbox\" name=\"RELAY1\" value=\"ON\"%RL1>Relay 01</p>"
"<p align=\"left\"><input type=\"checkbox\" name=\"RELAY2\" value=\"ON\"%RL2>Relay 02</p>"
"<p align=\"left\"><input type=\"checkbox\" name=\"RELAY3\" value=\"ON\"%RL3>Relay 03</p>"
"<p align=\"left\"><input type=\"checkbox\" name=\"RELAY4\" value=\"ON\"%RL4>Relay 04</p>"
"<p align=\"left\"><input type=\"submit\" value=\"Submit\" name=\"CTRL\"></p>"
"</form>"
"</div>"
"</td>"

"<td style=\"padding: 5px 5px 5px 5px;\" width=\"50%\">"


"<div>"
"<table border=\"1\" width=\"100%\" id=\"table1\">"
"<tr>"
"<td>Environment Sensors</td>"
"<td width=\"42\">Value</td>"
"<td width=\"33\">Unit</td>"
"<td width=\"150\">&nbsp;</td>"
"</tr>"
"<tr>"
"<td>Sensor 01</td>"
"<td width=\"42\">%AD0</td>"
"<td width=\"33\"><sup>o</sup>C</td>"
"<td width=\"150\">&nbsp;</td>"
"</tr>"
"<tr>"
"<td>Sensor 02</td>"
"<td width=\"42\">%AD1</td>"
"<td width=\"33\"><sup>o</sup>C</td>"
"<td width=\"150\">&nbsp;</td>"
"</tr>"
"</table>"
"</div>"
"</td>"
"</tr>"
"</tbody>"
"</table>"
"</td>"
"</tr>"
"</tbody>"
"</table>"
"<br><br><br>"
"<div align=\"center\">Timezone: GMT+7. Current time <span>%TI</span>.</div>"
"<br>"
"</div>"
"</div>"
"</div>"
"<form action=\"footer\" method=\"get\">"
"<br>"
"<div align=\"center\">"
"<div align=\"center\">Designed by thanh - tam</div>"
"</div>"
"</form>"
"</td>"
"</tr>"
"</tbody>"
"</table>"
"</div>"
"</body>"
"</html>"};
//---------------------------------------------------------------------------#endif //WEBPAGE_H
Ai m li th copy y chang file ny, kt qu l trang web s c hnh ch cn nh mnh.
Tip theo, ta quay li file "http.h". Thm cc define cho cc method ca request:
Code:
//
#define
#define
#define
#define
//
#define
#define
#define
//

HTTP_REQUEST_GET
HTTP_REQUEST_POST
HTTP_REQUEST_HEAD
HTTP_REQUEST_UNKNOWN
HTTP_REQUEST_GET_STR
HTTP_REQUEST_POST_STR
HTTP_REQUEST_HEAD_STR

1//"GET"
2//"POST"
3//"HEAD"
4//Request quai qui gi do ma ta khong biet
"GET"
"POST"
"HEAD"

Sau l khai bo struct tng ng vi bn tin request:


Code:
//

struct httpRequest{
unsigned char method;
unsigned char *requestURI;
unsigned char *version;
unsigned char *header;
unsigned char *body;
unsigned int bodyLen;
};

//end
//end
//end
//end
//

with
with
with
with

space
space
\n\r
\n\r\n\r

y cc bn lu l khc vi cc header khc, ta dng ch yu bin con tr tr cc field trong bn tin request, v
kch thc cc field trong bn tin khng c nh, nn v tr bt u field cng khng c nh. Ta dng bin co tr tr
n u mi field, cn kt thc field th ng nhin l trc khi bt u filed tip theo, tr field cui cng l body, ta cho
n 1 bin chiu di.
Webserver phi c kh nng thit lp ng thi nhiu phin kt ni, do ta khai bo 1 struct na lu thng tin v mi
phin kt ni HTTP:
Code:
struct httpSession{
unsigned char status;
const prog_char *headerPointer;
const prog_char *bodyPointer;
unsigned char *authStr;
unsigned char auth;
struct httpRequest rqst;
struct tcpSession *pTCPSession;
};

//Trang thai hien tai


//Con tro den header trong bo nho chuong trinh
//Con tro den du lieu can gui trong bo nho chuong trinh
//Con tro den chuoi xac thuc
//Xac thuc
//Request tuong ung

Trong struct trn ta c dng t kha prog_char ( ch b nh chng trnh: ROM) nn cc bn nh include file
"pgmspace.h" vo (u file) nu khng s c bo li:
Code:
#include <avr/pgmspace.h>
Cui cng l define cc trng thi ca 1 phin HTTP v s phin ti a c th thit lp ng thi:
Code:
//
#define
#define
#define
#define
#define
//
#define
//

HTTP_STATUS_IDLE
HTTP_STATUS_GOT_REQUEST
HTTP_STATUS_HEADER_SENT
HTTP_STATUS_HEADER_RECEIVED
HTTP_STATUS_FINISH

0
1
2
3

MAX_HTTP_SESSION

Ti lt file source "http.c"


u tin ta khai bo mt s bn tin response chun webserver s dng:
Bn tin response cho mt request GET/POST hp l, km theo s l ni dung trang web:
Code:
prog_char http_pageheader_ok[]={

"HTTP/1.0 200 Document follows\r\n"


"Server: AVR_Small_Webserver\r\n"
"Content-Type: text/html\r\n\r\n"};

Trn y l Status-line v Response Header, Entity Header ca bn tin response, phn Entity-body chnh l ni dung
webpage m ta chun b trong file "webpage.h"
Bn tin response yu cu xc thc. Tt nhin trang web remote control ca chng ta phi c xc thc
username/password ri, chc cc bn khng mun ai cng c th truy cp vo bt tt thit b lung tung ch.
Code:
prog_char http_pageheader_unauth[]={

"HTTP/1.0 401 Unauthorized\r\n"


"Server: AVR_Small_Webserver\r\n"
"WWW-Authenticate: Basic

realm=\"NeedPassword\""
"\r\nContent-Type:
text/html\r\n\r\n"};

Bn tin bo vic xc thc tht bi:


Code:
prog_char http_pageheader_auth_error[] = {"401 Unauthorized%END"};
Bn tin bo li request mt i tng khng c:
Code:
prog_char http_error_notimp[]={

"HTTP/1.1 501 Not Implemented\r\n"


"Server: AVR_Small_Webserver\r\n"
"WWW-Authenticate: Basic realm=\"My

AVR web server\""


"\r\nContent-Type:
text/html\r\n\r\n"};
Khai bo 1 array cc bin struct cha thng tin v cc phin HTTP:
Code:
struct httpSession

httpSessionTable[MAX_HTTP_SESSION];

Khai bo 1 char array cha chui xc thc:


Code:
unsigned char http_auth_password[20];
u tin, ta vit hm tnh m xc thc cho username/password:
Code:
//---------------------------------------------------------------------------PROGMEM char BASE64CODE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
//
void decode_base64 (unsigned char *str1_in,unsigned char *str2_out)
{
unsigned char *strp;
unsigned char end_byte = 0;
strp = str2_out;
while (*str1_in != 0)
{
*str2_out++= (*str1_in & 0xFC)>>2;
*str2_out = (((*str1_in++)&0x03)<<4);
if (*str1_in==0)
{
str2_out++;
end_byte = 2;
break;
}
else
{
*str2_out++ += ((*str1_in & 0xF0)>>4);
*str2_out = (((*str1_in++)& 0x0F)<<2);
if (*str1_in==0)
{
str2_out++;
end_byte = 1;
break;
}
else
{
*str2_out++
+= ((*str1_in & 0xC0)>>6);
*str2_out++= *str1_in++ & 0x3F;
}
}
}
*str2_out = 0;
while(strp != str2_out)
{
*strp = pgm_read_byte(&BASE64CODE[(*strp) & 0x3F]);
strp++;
}

while (end_byte--)
{
*strp = '=';
strp++;
}
*strp = 0;
}
Hm khi to giao thc HTTP (thc cht l khi to gi tr ban u cho cc bin):
Code:
//---------------------------------------------------------------------------void httpInit()
{
unsigned char i;
decode_base64((unsigned char*)HTTP_AUTH_STRING,http_auth_password);
for(i=0; i < MAX_HTTP_SESSION; i++){
httpSessionTable[i].status = HTTP_STATUS_IDLE;
}
//UpdateCtrlSts(0x00);
}
Ta m file "ntAVRnet.h" khai bo chui xc thc username/password cho trang web ca chng ta (gi s username l
admin, password l 1234):
Code:
#define HTTP_AUTH_STRING "admin:1234"
Tip theo, ta vit hm x l 1 request nhn c. Lc ny, request nhn c qua port TCP 80 ang nm trn buffer,
ngay sau TCP Header. Nhim v ca hm ny l xc nh phng thc (method) ca request, xc nh v tr cc field, v
lu nhng thng tin ny vo struct httpRequest tng ng.
Code:
//---------------------------------------------------------------------------//Ham xu ly mot request cua giao thuc HTTP
void httpGetRequest(unsigned char *buffer,unsigned int bufferLen,struct httpRequest* rqst)
{
unsigned int i;
if((buffer[0] == 'G')&&(buffer[1] == 'E')&&(buffer[2] == 'T')){
rqst->method = HTTP_REQUEST_GET;
#ifdef HTTP_DEBUG
printf("GET\r\n");
#endif
}else if((buffer[0] == 'P')&&(buffer[1] == 'O')&&(buffer[2] == 'S')&&(buffer[3] == 'T')){
rqst->method = HTTP_REQUEST_POST;
#ifdef HTTP_DEBUG
printf("POST\r\n");
#endif
}else if((buffer[0] == 'H')&&(buffer[1] == 'E')&&(buffer[2] == 'A')&&(buffer[3] == 'D')){
rqst->method = HTTP_REQUEST_HEAD;
#ifdef HTTP_DEBUG
printf("HEAD\r\n");
#endif
}else{
rqst->method = HTTP_REQUEST_UNKNOWN;
#ifdef HTTP_DEBUG
printf("UNKNOWN\r\n");
#endif
}
//Bat dau tim URI va HTTP version
i = 0;
while(++i<bufferLen){
if(buffer[i] == ' '){
//khoang trang dau tien
rqst->requestURI = &buffer[i+1];
break;
}
}
while(++i<bufferLen){
if(buffer[i] == ' '){
//khoang trang dau tien
rqst->version = &buffer[i+1];
break;
}
}

//Tim header
while(++i<bufferLen){
if((buffer[i] == 0x0d) && (buffer[i+1] == 0x0a)){ //\n\r dau tien, bat dau header
rqst->header = &buffer[i+2];
break;
}
}
//Tim ket thuc header
while(++i<bufferLen){
if((buffer[i] == 0x0d) && (buffer[i+1] == 0x0a) && (buffer[i+2] == 0x0d)){
//\n\r\n\r
i += 4;
break;
}
}
rqst->body = &buffer[i];
rqst->bodyLen = bufferLen - i;
#ifdef HTTP_DEBUG
printf("Buffer Len:%d\r\n",bufferLen);
printf("URI start:%d\r\n",(rqst->requestURI - buffer));
printf("HTTP Version:%d\r\n",(rqst->version - buffer));
printf("Header:%d\n\r",(rqst->header - buffer));
printf("Body:%d\n\r",(unsigned int)(rqst->body - buffer));
printf("Body:%x-%x\n\r",(unsigned int)(rqst->body),(unsigned int)buffer);
printf("Body i:%d\n\r",i);
#endif
}
V hm ly gi tr ca 1 trng HTTP Header:
Code:
//---------------------------------------------------------------------------//Ham lay gia tri mot truong trong HTTP Header,
// tra lai con tro vi tri bat dau value cua truong nay
unsigned char * httpHeaderGetField(const prog_char fieldname[],struct httpRequest *rqst)
{
unsigned char *header;
unsigned int i,j,headerLen;
header = rqst->header;
headerLen = (rqst->header) - (rqst->body) - 4;
i=0;
j=0;
while(i<headerLen){
if(header[i++] != pgm_read_byte(fieldname + j++)){
j = 0;
}
if(pgm_read_byte(fieldname + j) == 0){
return(header+i+2);
}
}
return(0);
}
Tip theo, ta vit 2 hm chnh ca giao thc HTTP: hm gi mt bn tin HTTP i v hm x l 1 request nhn c:
u tin, ta cn 2 hm tm kim chui m ta s s dng trong 2 hm chnh trn:
- Hm tm 1 chui lu trong b nh chng trnh (ROM) trong 1 chui lu trong RAM
Code:
//---------------------------------------------------------------------------unsigned int findstr(const prog_char progstr[],unsigned char* str,unsigned int len)
{
unsigned int i,j;
i=0;
j=0;
while(i<len){
if(str[i++] != pgm_read_byte(progstr + j++)){
j = 0;
}
if(pgm_read_byte(progstr + j) == 0){
return(i-j);

}
}
return(-1);
}
- Hm tm 1 chui lu trong b nh RAM trong 1 chui cng lu trong RAM
Code:
//---------------------------------------------------------------------------unsigned int findstrdatamem(unsigned char* str1,unsigned char* str2,unsigned int len)
{
unsigned int i,j;
i=0;
j=0;
while(i<len){
if(str2[i++] != str1[j++]){
j = 0;
}
if(str1[j] == 0){
return(i-j);
}
if(str2[i] == 0){
return(-1);
}
}
return(-1);
}
V y l hm gi i mt bn tin HTTP:
Code:
//---------------------------------------------------------------------------//Ham gui mot doan du lieu chua trong bo nho chuong trinh ra theo giao thuc HTTP
void
HTTPSend(const prog_char progdata[],unsigned int dataLen,struct tcpSession *pSession, unsigned
char endData)
{
unsigned int i;
unsigned int srcDataIdx = 0;
unsigned char* dataBuffer;
unsigned char Flags;
unsigned char tmpChr;
Flags = TCP_PSH_FLAG;
dataBuffer = ethGetBuffer() + ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN;
if(dataLen == 0){
Flags |= TCP_ACK_FLAG;
if(endData){
if(srcDataIdx == dataLen){
Flags |= TCP_FIN_FLAG;
pSession->sesState = TCP_STATE_FIN_WAIT1;
}
}
TCPPackedSend(pSession,Flags,0,dataBuffer);
}
while(srcDataIdx < dataLen){
i = 0;
while(i<MAX_SEGMENT_SIZE){
tmpChr = pgm_read_byte(progdata + srcDataIdx++);
dataBuffer[i++] = tmpChr; //Copy data to tcp data buffer
if(srcDataIdx==dataLen){
break;
}
}
Flags |= TCP_ACK_FLAG;
if(endData){
if(srcDataIdx == dataLen){
Flags |= TCP_FIN_FLAG;
pSession->sesState = TCP_STATE_FIN_WAIT1;
}
}
TCPPackedSend(pSession,Flags,i,dataBuffer);
//delay_ms(100);
#ifdef NETSTACK_DEBUG

printf("Sent %d byte\r\n",srcDataIdx);
#endif
}
}
Hm x l 1 request nhn c:
Code:
//---------------------------------------------------------------------------//Ham xu ly mot goi thuoc giao thuc HTP nhan duoc
void httpDataIn(unsigned char *buffer,unsigned int bufferLen,struct tcpSession *pSession)
{
unsigned char i;
unsigned char *tmpstr;
prog_char Auth_str[]="Authorization";
//Tim xem cophien HTTP service da co cho phien TCP nay khong
for(i=0; i < MAX_HTTP_SESSION; i++){
if((httpSessionTable[i].status != HTTP_STATUS_IDLE) &&
(httpSessionTable[i].pTCPSession == pSession))
break;
}
if(i == MAX_HTTP_SESSION){
//Tim 1 phien trong
for(i=0; i < MAX_HTTP_SESSION; i++){
if(httpSessionTable[i].status == HTTP_STATUS_IDLE){
httpSessionTable[i].pTCPSession = pSession;
break;
}
}
}
if(httpSessionTable[i].status == HTTP_STATUS_IDLE){
//Neu day la 1 HTTP request moi
//Kiem tra method cua request
httpGetRequest(buffer,bufferLen,&(httpSessionTable[i].rqst));
if(httpSessionTable[i].rqst.method == HTTP_REQUEST_UNKNOWN){
//Neu request khong biet, thoat tro ve trang thai idle
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}else{
//Set trang thai cua HTTP session thanh HEADER_RECEIVED (da nhan header)
httpSessionTable[i].status = HTTP_STATUS_HEADER_RECEIVED;
}
}
//Neu da nhan header
if(httpSessionTable[i].status == HTTP_STATUS_HEADER_RECEIVED){
//Kiem tra xem da xac thuc hay chua
if(httpSessionTable[i].auth != 1){
tmpstr = httpHeaderGetField(Auth_str,&(httpSessionTable[i].rqst));
if(findstrdatamem(http_auth_password,tmpstr,httpSessionTable[i].rqst.bodytmpstr) != -1){
#ifdef HTTP_DEBUG
printf("Auth OK\n\r");
printfStr(http_auth_password);
printf("Input\n\r");
printfStr(tmpstr);
#endif
httpSessionTable[i].auth = 1;
//Neu xac thuc khong hop le
}else{
#ifdef HTTP_DEBUG
printf("Auth fail\n\r");
printf("Auth string:");
printfStr(http_auth_password);
printf("\n\r");
printf("Received string:");
printfStrLen(tmpstr,0,20);
#endif
HTTPSend(http_pageheader_unauth,sizeof(http_pageheader_unauth)1,pSession,0);
HTTPSend(http_pageheader_auth_error,sizeof(http_pageheader_auth_error)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}

}
//Process for each method
//If GET method
if(httpSessionTable[i].rqst.method == HTTP_REQUEST_GET){
#ifdef HTTP_DEBUG
printf("GET HEADER:\n\r");
printfStrLen(httpSessionTable[i].rqst.header,0
,(httpSessionTable[i].rqst.body httpSessionTable[i].rqst.header) + httpSessionTable[i].rqst.bodyLen);
#endif
//If GET the main website
if((httpSessionTable[i].rqst.requestURI[0] == '/') &&
(httpSessionTable[i].rqst.requestURI[1] == ' ')){
HTTPSend(http_pageheader_ok,sizeof(http_pageheader_ok)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
//If error
}else{
HTTPSend(http_error_notimp,sizeof(http_error_notimp),pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
}
return;
//If POST method
}else if(httpSessionTable[i].rqst.method == HTTP_REQUEST_POST){
//Update POST data
if(findstr(PSTR("SUB=Submit"),buffer,bufferLen) != -1){
//Send HTTP data
HTTPSend(http_pageheader_ok,sizeof(http_pageheader_ok)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}else if(findstr(PSTR("APPLY=Apply"),buffer,bufferLen) != -1){
HTTPSend(http_pageheader_ok,sizeof(http_pageheader_ok)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
}else{
HTTPSend("",0,pSession,0);
}
}
}
}
Trong cc hm trn ta c gi hm ca giao thc TCP nn cc bn include file "tcp.h" vo u file nh:
Code:
#include "tcp.h"
V nh thm khai bo cc hm vit vo file header "http.h"
c th bin dch v khi ng webserver, ta cn sa 1 t trong chng trnh chnh.
M file "ntAVRnet.h", thm vo cc include 2 file "tcp.h" v "http.h":
Code:
#include "tcp.h"
#include "http.h"
Thm vo hm netInit lnh khi ng giao thc TCP v HTTP:
Code:
TCPInit();
httpInit();
Thm vo hm main lnh khi ng phin TCP port 80 trng thi listen cho dch v HTTP (trc vng lp while(1)):
Code:
TCPCreateSession(80,httpDataIn);
By gi cc bn c th bin dch v chy th, c th truy cp web nhng cha c chc nng gim st v iu khin t xa
qua webserver, i bi tip theo nh

Nguyn vn bi hieuvip88
th y lm cho em hi t.
em mun thay code iu khin sng tt led(relay) bng code iu xung c ko ?
th y ch gip em thut ton ca vic iu khin sng tt led khi nhn c yu cu t trang web ko ? cm n thy nhiu
Lu nay bn cng vic gia nh v c quan nhiu qu nn b ri Thread, nay rnh ri cht li tr li mi ngi tip nh:
1-c, cch thc hin cn ty bn iu xung bng Timer hay vng lp,...
2-Thut ton iu khin relay hay led g nh sau:
Khi my tnh ti ni dung trang web v trnh duyt, trn trang web s c 1 on code HTML m t mt nt bm hoc 1
nt check, v d:
Code:
<form method="post" action="">
<p align="left"><input type="checkbox" name="OUT" value="C" checked>Aqua Lamp</p>
<p align="left"><input type="checkbox" name="OUT" value="B">Filter</p>
<p align="left"><input type="checkbox" name="OUT" value="A">Chiller</p>
<p align="left"><input type="checkbox" name="OUT" value="D">Cooler Fan</p>
<p align="left"><input type="submit" value="Submit" name="SUB"></p>
</form>
on code trn s to ra 1 form gm c 4 nt check (type="checkbox") v text hin th bn cnh tng ng l:Aqua
Lamp,Filter,Chiller,Cooler Fan. Dng no c t kha checked l check box ang c chn.

on code trn cng qui nh cc input m ngi dng nhp vo (gi tr check) s c gi tr li cho webserver bng
phng thc http post (method="post").
Sau khi ta nh du vo cc v nhn nt Submit, my tnh s gi n webserver 1 bn tin http post vi gi tr ca cc
check c cha trong phn body ca bn tin post (xem li cu trc bn tin http post phn trc.
Nh vy trong chng trinh trn AVR, on code x l bn tin http nhn c (hm httpDataIn ta cn x l bn tin ny.
C th trong on code cho trng hp bn tin l http post (else if(httpSessionTable[i].rqst.method ==
HTTP_REQUEST_POST)), ta cn c ni dung bn tin, tm kim cc gi tr: OUT=A (Relay 1); OUT=B (Relay 2); OUT=C
(Relay 3); OUT=D (Relay 4); (OUT l trng name ca code HTML ca check, A,B,C,D l trng value). Khi thy gi tr
tng ng th ta ng ngt re lay tng ng thi.
Cng vic vn vy, c khi cn bn rn hn, chn qu, lm hoi khng ht, vic u c n n ko ti.
Ni chung cch lm nh sau:
I-Cp nht trng thi cc relay v gi tr sensor cho Web:
Mi ngi l trong ni dung trang web, ch gi tr ca relay v sensor mnh 1 keyword tng ng, l: %RL1,
%RL2, %RL3, %RL4 v %AD0, %AD1.
Ch ny chnh l ch cn thay th cc gi tr tng ng trc khi gi ni dung xung cho client.
Vy trong hm HTTPSend() (hm gi ni dung web xung client) cn sa li cp nhp cc thng tin ny. V d nh
sau:
Code:
void
HTTPSend(const prog_char progdata[],unsigned int dataLen,struct tcpSession *pSession, unsigned
char endData)
{
unsigned int i;
unsigned int srcDataIdx = 0;
unsigned char* dataBuffer;
unsigned char Flags;
unsigned char tmpChr,tmpVar;
unsigned char* tmpStr;
Flags = TCP_PSH_FLAG;
dataBuffer = ethGetBuffer() + ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN;
if(dataLen == 0){
Flags |= TCP_ACK_FLAG;
if(endData){
if(srcDataIdx == dataLen){
Flags |= TCP_FIN_FLAG;

pSession->sesState = TCP_STATE_FIN_WAIT1;
}
}
TCPPackedSend(pSession,Flags,0,dataBuffer);
}
while(srcDataIdx < dataLen){
i = 0;
while(i<MAX_SEGMENT_SIZE){
tmpChr = pgm_read_byte(progdata + srcDataIdx++);
if(tmpChr == '%'){
//Truong hop ung voi dieu khien relay ("%RLx) hay
gia tri AD ("%ADx")
if( (i + 9) > MAX_SEGMENT_SIZE){ //Neu khong con du cho trong tren
buffer
srcDataIdx--;
break;
}
//Tiep tuc neu du cho trong tren buffer
tmpVar = pgm_read_byte(progdata + srcDataIdx + 3) - 0x30;
if((pgm_read_byte(progdata + srcDataIdx) == 'R') &&
(pgm_read_byte(progdata + srcDataIdx + 1) == 'L')){
if(GetRelayState(tmpVar)){//checked
dataBuffer[i++] = ' ';dataBuffer[i++] =
'c';dataBuffer[i++] = 'h';dataBuffer[i++] = 'e';
dataBuffer[i++] = 'c';dataBuffer[i++] =
'k';dataBuffer[i++] = 'e';dataBuffer[i++] = 'd';
}
srcDataIdx += 4;
}else if((pgm_read_byte(progdata + srcDataIdx) == 'A') &&
(pgm_read_byte(progdata + srcDataIdx + 1) == 'D')){
tmpStr = (unsigned
char*)uInt2StrLen(LM35_TYP_DECODE(GetADC(tmpVar)),3);//(unsigned char*)uByte2Str(GetAD(tmpChr));
tmpVar = 0;
dataBuffer[i++] = tmpStr[tmpVar++];
dataBuffer[i++] = tmpStr[tmpVar++];
dataBuffer[i++] = '.';
dataBuffer[i++] = tmpStr[tmpVar++];
//while(tmpStr[tmpChr] != 0){
//
dataBuffer[i++] = tmpStr[tmpChr++];
//}
srcDataIdx += 4;
}else{// Neu truong hop khac:
dataBuffer[i++] = tmpChr;
}
}
else{
dataBuffer[i++] = tmpChr; //Copy data to tcp data buffer
}
if(srcDataIdx==dataLen){
break;
}
}
Flags |= TCP_ACK_FLAG;
if(endData){
if(srcDataIdx == dataLen){
Flags |= TCP_FIN_FLAG;
pSession->sesState = TCP_STATE_FIN_WAIT1;
}
}
TCPPackedSend(pSession,Flags,i,dataBuffer);
//delay_ms(100);
#ifdef NETSTACK_DEBUG
printf("Sent %d byte\r\n",srcDataIdx);
#endif
}
}
//-------------------------------------------------------------------------------------Cc bn thy kh n gin, khi tm thy k t %, nu tip theo l RL1 (%RL1) th ta thay trng thi ca Relay 1 vo: nu
Relay 1 ang ng th gi tr l "checked", nu Relay 1 ang nh, th trng (hay "unchecked").
Tng t, nu k t tip theo l AD0 (%AD0) th ta thay gi tr tng ng c t ADC vo.
Ch khi thay cc gi tr tng ng ta phi tng bin m (srcDataIdx) ln tng ng vi chiu di m ta thm vo.

II-iu khin relay khi nhn c HTTP post (ngi dng nhn nt Submit trn trang web):
Ci ny ta phi sa trong hm HTTPDataIn(), phn x l bn tin HTTP POST
V d:
Code:
//-------------------------------------------------------------------------------------//Ham xu ly mot goi thuoc giao thuc HTP nhan duoc
void httpDataIn(unsigned char *buffer,unsigned int bufferLen,struct tcpSession *pSession)
{
unsigned char i;
unsigned char *tmpstr;
unsigned char tmpRelaySts;
//struct httpRequest rqst;
//Tim xem cophien HTTP service da co cho phien TCP nay khong
for(i=0; i < MAX_HTTP_SESSION; i++){
if((httpSessionTable[i].status != HTTP_STATUS_IDLE) &&
(httpSessionTable[i].pTCPSession == pSession))
break;
}
if(i == MAX_HTTP_SESSION){
//Tim 1 phien trong
for(i=0; i < MAX_HTTP_SESSION; i++){
if(httpSessionTable[i].status == HTTP_STATUS_IDLE){
httpSessionTable[i].pTCPSession = pSession;
break;
}
}
}
if(httpSessionTable[i].status == HTTP_STATUS_IDLE){
//If this is a new HTTP request
//Check for request method
httpGetRequest(buffer,bufferLen,&(httpSessionTable[i].rqst));
//TCPPackedSend(pSession,(TCP_ACK_FLAG),0,buffer);
if(httpSessionTable[i].rqst.method == HTTP_REQUEST_UNKNOWN){
//if invalid request, just cancel
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}else{
//Set HTTP session to HEADER_RECEIVED (for next process)
httpSessionTable[i].status = HTTP_STATUS_HEADER_RECEIVED;
}
}
//If got header
if(httpSessionTable[i].status == HTTP_STATUS_HEADER_RECEIVED){
//Check for auth string
if(httpSessionTable[i].auth != 1){
tmpstr = httpHeaderGetField(Auth_prog,&(httpSessionTable[i].rqst));
if(findstrdatamem(http_auth_password,tmpstr,httpSessionTable[i].rqst.bodytmpstr) != -1){
#ifdef HTTP_DEBUG
printf("Auth OK\n\r");
printfStr(http_auth_password);
printf("Input\n\r");
printfStr(tmpstr);
#endif
httpSessionTable[i].auth = 1;
//If not valid auth
}else{
#ifdef HTTP_DEBUG
printf("Auth fail\n\r");
printf("Auth string:");
printfStr(http_auth_password);
printf("\n\r");
printf("Received string:");
printfStrLen(tmpstr,0,20);
#endif
HTTPSend(http_header3,sizeof(http_header3)-1,pSession,0);
HTTPSend(Page0,sizeof(Page0)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}
}
//Process for each method
//If GET method
if(httpSessionTable[i].rqst.method == HTTP_REQUEST_GET){

#ifdef HTTP_DEBUG
printf("GET HEADER:\n\r");
printfStrLen(httpSessionTable[i].rqst.header,0
,(httpSessionTable[i].rqst.body httpSessionTable[i].rqst.header) + httpSessionTable[i].rqst.bodyLen);
#endif
//If GET the main website
if((httpSessionTable[i].rqst.requestURI[0] == '/') &&
(httpSessionTable[i].rqst.requestURI[1] == ' ')){
HTTPSend(http_header1,sizeof(http_header1)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
//If error
}else{
HTTPSend(http_error_notimp,sizeof(http_error_notimp),pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
}
return;
//If POST method
}else if(httpSessionTable[i].rqst.method == HTTP_REQUEST_POST){
//Update POS data
if(findstr(PSTR("SUB=Submit"),buffer,bufferLen) != -1){
tmpRelaySts = 0x00;
if((findstr(PSTR("RELAY1=ON"),buffer,bufferLen)) != -1){
//SetRelayState(1,1);
tmpRelaySts += 1;
#ifdef HTTP_DEBUG
printf("Relay 1 on\r\n");
#endif
}else{
//SetRelayState(1,0);
//tmpRelaySts += 2;
#ifdef HTTP_DEBUG
printf("Relay 1 off\r\n");
#endif
}
if((findstr(PSTR("RELAY2=ON"),buffer,bufferLen)) != -1){
//SetRelayState(2,1);
tmpRelaySts += 2;
#ifdef HTTP_DEBUG
printf("Relay 2 on\r\n");
#endif
}else{
//SetRelayState(2,0);
//tmpRelaySts += 8;
#ifdef HTTP_DEBUG
printf("Relay 2 off\r\n");
#endif
}
if((findstr(PSTR("RELAY3=ON"),buffer,bufferLen)) != -1){
//SetRelayState(3,1);
tmpRelaySts += 4;
#ifdef HTTP_DEBUG
printf("Relay 3 on\r\n");
#endif
}else{
//SetRelayState(3,0);
#ifdef HTTP_DEBUG
printf("Relay 3 off\r\n");
#endif
}
if((findstr(PSTR("RELAY4=ON"),buffer,bufferLen)) != -1){
//SetRelayState(4,1);
tmpRelaySts += 8;
#ifdef HTTP_DEBUG
printf("Relay 4 on\r\n");
#endif
}else{
//SetRelayState(4,0);
#ifdef HTTP_DEBUG
printf("Relay 4 off\r\n");
#endif
}
UpdateCtrlSts(tmpRelaySts);

//Send HTTP data


HTTPSend(http_header1,sizeof(http_header1)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
return;
}else if(findstr(PSTR("APPLY=Apply"),buffer,bufferLen) != -1){
HTTPSend(http_header1,sizeof(http_header1)-1,pSession,0);
HTTPSend(Page1,sizeof(Page1)-1,pSession,1);
httpSessionTable[i].status = HTTP_STATUS_IDLE;
}else{
HTTPSend("",0,pSession,0);
}
}
}
}
//-------------------------------------------------------------------------------------Gii thch:
- Khin ngi dng nhn Submit, client s gi 1 bn tin HTTPPost, request chnh trang web , nhng trong mesage body
c cha thng tin ly t form trn trang web (trng thi cc n check m ngi dng thay i).
- V d, trn trang web (trong webpage.h) ta khai bo cc check nh sau:
<p align="left"><input type="checkbox" name="RELAY1" value="ON"%RL1>Relay 01</p>
<p align="left"><input type="checkbox" name="RELAY2" value="ON"%RL2>Relay 02</p>
<p align="left"><input type="checkbox" name="RELAY3" value="ON"%RL3>Relay 03</p>
<p align="left"><input type="checkbox" name="RELAY4" value="ON"%RL4>Relay 04</p>
i vi relay 1, khai bo nh vy tc l tn i tng l RELAY1 (name="RELAY1"), gi tr nhn c khi n c check
l ON (value="ON")
Nh vy gi s cc check box 1 v 3 c check, 2 v 4 b trng, th khi nhn Submit, thng tin sau s c gi i:
RELAY1=ON
RELAY3=ON
Cn iu khin relay th no l do cc bn thi. trong v d trn mnh lu trng thi cc relay trong bin tmpRelaySts,
sau mi gi hm UpdateCtrlSts(tmpRelaySts) thc thi cc trng thi .
Chc cc bn thnh cng. Xin li v mi ngi i qu lu.

You might also like