[MREPRO] 4. domaća zadaća - 2019/2020
Sashat_Triceps
E kako definirati buffer za primanje RREQ zahtjeva? U specifikacijama kaže 2 bajta za code ( uint_16t), al onda za ime datoteke kaze samo “string” i kasnije isto tako za polje načina prijenosa.
Koliko taj “string” mora biti velik? Jel postoji neki pametniji način od toga da uzmem char polje malo veće duljine i iz njega sa strtok odvojim ime datoteke i način prijenosa?
Gussy
Sasha_Triceps Ne vidim ni u ovom RFC 1350 da igdje piše koliko dugačak mora biti taj string filename, pa stavi tipa 256 ili nešto tako. Mislim da to nije toliko bitno. Za međuispit i za ove labose itd., ja sam radio posebne structove za tipove paketa koji koristim u tom zadatku. Npr. struct za rip paket iz meduispita.
struct rip_entry
{
unsigned int af_identifier : 16;
unsigned int route_tag : 16;
unsigned int ip_address : 32;
unsigned int subnet_mask : 32;
unsigned int next_hop : 32;
unsigned int metric : 32;
};
struct rip_packet
{
unsigned int command : 8;
unsigned int version : 8;
unsigned int must_be_zero : 16;
struct rip_entry entries[MAX_ENTRY];
};
Ovi brojevi pored svakog elementa structa se zovu bit field i označavaju koliko bitova zauzima taj element unutar samog structa, ako piše 16, to znači 2 bytea. Nisam siguran ako koristiš bit field za neki element unutar structa, da li onda svi elementi isto moraju koristiti bit fieldove ili mogu biti i elementi za koje nije definirana veličina bitova na ovaj način.
Tj. može li se ovako:
struct foo
{
int a : 16;
int b;
}
Po nekoj logici ovaj int a bi bio veličine 2 bajta, a int b bi zauzimao normalnu količinu memorije koliko int zauzima. Pretpostavljam da i ovo radi.
Gussy
Sasha_Triceps Lol sad sam skuzio o cemu pricas i ovaj moj odgovor nema veze s tim, al cu svejedno ostavit. Ionako ne mogu obrisat.
Nisam siguran kako bi se trebalo “odvojiti” taj string od ostatka poruke, tj. skuziti gdje zavrsava.
https://github.com/crossbowerbt/tftpserver/blob/master/tftpserv.c
Ovdje je lik iskoristio \0
da nađe gdje završava filename.
Gussy
Jeste li napravili poseban struct za svaki mogući tip paketa?
Sashat_Triceps
huba buba Hvala ti na dužem odgovoru 🙂
Napravio sam zadaću u međuvremenu, u biti sam puknuo char polje "Data"velicine 100, poslije codea od 2 bajta, pa se onda kasnije drkas sa izvlacenjem file namea i nacina prijenosa. Stvar je u tome sto oni nisu zapravo odvojeni sa tom nulom kao što je u specifikaciji. Kad sam testirao s wiresharkom odvojeni su s \0 , a 0 dolazi tek na kraju paketa, tako daa nez tko tu koga laže . Koristio sam isti delimiter ko taj lik i radi
Gussy
Sasha_Triceps Ocu stici do sutra napisati sve? Ima milijun stvari koje se trebaju implementirati.
Sashat_Triceps
huba buba Pa ovisi koliko si napravio, najviše vremena će ti uzet obrada tekstualne datoteke za \n -ove. Poslije toga ovo ostalo ide glatko
Gussy
Sasha_Triceps Kako si riješio taj problem sa zamjenjivanjem \n sa \r\n jer se ne treba “samo” zamijeniti kako oni kazu nego moras dodati jos jedan znak i onda cijela ta obrada ode u kurac.
Sashat_Triceps
huba buba Učitaš podatke iz filea u neko polje. Zatim u petlji ides bajt po bajt kroz to polje i stavljaš bajtove u buffer za slanje. Kad naiđes na \n , u istoj iteraciji stavi \r zatim \n u buffer.
Gussy
Sasha_Triceps Jel misliš sve podatke iz filea staviti u jedno polje?
Cvija
A kako se postiže konkurentnost?
Jel moram raditi one forkove pa da svako dijete obrađuje svakog klijenta ili postoji neki drugi način?
U TFTP-u u knjizi se spominje neka konkurentnost mijenjanjem portova prilikom slanja paketa
Sashat_Triceps
Cvija Sa dretvama ti je najjednostavnije, svaka dretva obrađuje jednog klijenta i stvara novi socket. S time postižeš i konkurentnost opisanu u tftpu ( tftp server prima zahtjeve na jedan port, ali odgovara na drugom)
Cvija
A kako si provjeravao je li netascii ili octet u poruci koju prima prilikom RRQ?
Jer meni nekako sve proguta u filename
Cvija
Cvija Napravio sam strukture koje pokrivaju svaki dio
Ovako mi izgleda struktura koja pokriva dio za primanjem zahtjeva:
struct tftp_rrq{
uint16_t code;
uint8_t filename[512];
uint8_t zero;
uint8_t mode[30];
uint8_t zero2;
};
Sashat_Triceps
Cvija Ovako mi izgleda struktura za primanje zahtjeva :
`
struct RRQbuffer{
u_int16_t code;
char fileNameAndMode[100];
};
`
Kasnije u kodu sa strtok-om i u programu izdvojis filename i mode, a strcmp-om usporedis string u modeu s “netascii”, odnosno “octet”
Gussy
Cvija problem ti je što taj rrq paket nema određenu dužinu i koliko sam ja razumio iz specifikacije, ta dva “zero” dijela paketa su zapravo \0
.
Cvija
Sasha_Triceps E vidiš, kad tako primim podatak, problem mi je što se u filenameimode spremi samo filename
Mode se ne spremi
Sashat_Triceps
huba buba Ne , mislim da učitavaš po dijelovima u polje. Fileovi su reda veličina nekoliko MB što uzima dosta memorije ako bi ga cijelog išao učitavat. Uzmeš polje od tipa 4KB, učitaš dio podataka u njega i obrađuješ ga. Kad ga obradiš uzmeš novi dio itd itd
Cvija
Cvija [EDIT] riješio
Ako netko ima takav problem, može npr. uzeti strlen od toga i na to mjesto postaviti neki delimiter s kojim će kasnije podijeliti string
Cvija
Treba li program nakon primanja datoteke se zatvoriti ili nastaviti s radom?