Ofte spurte spørsmål

Send spørsmål til inf3190-orakel@ifi.uio.no, eller møt til orakeltime på onsdager mellom kl 10:15–12:00 i Datastue Chill (3443).

Sockets

Skal jeg bruke gethostbyname() eller getaddrinfo()?

gethostbyname() er foreldet (obsolete), og det anbefales at nye programmer bruker getaddrinfo(). Begge alternativer er imidlertid mulig i løsningen din, og gir lik uttelling.

Funksjonene skiller seg ved at getaddrinfo() fungerer for flere adressefamilier enn IPv4, slik som IPv6. Forgjengeren gethostbyname() er derimot begrenset til IPv4-adresser.

Merk at maskinene på ifi per nå ikke har IPv6-forbindelse til Internett. Hvis du ønsker å teste hvorvidt koden din fungerer med IPv6, så kan du bruke SSH-serverne ulrik.uio.no og login.uio.no til dette. Dette er ikke et krav.

Hvordan vet man når en fullstendig ramme er mottatt?

UDP er datagramorientert, og ikke strømorientert slik som TCP. Ett receivekall på en UDP socket kan kun håndtere hele UDP-pakker (datagram). Dette er nærmere presisert på man-siden til udp(7):

All receive operations return only one packet. When the packet is smaller than the passed buffer, only that much data is returned; when it is bigger, the packet is truncated and the MSG_TRUNC flag is set.

Hvis du sender én ramme for hver sendto(), vil du også motta nøyaktig én ramme for hver recvfrom().

Obligatorisk oppgave

Hvor bør jeg starte?

Lag 1 er et greit sted å starte. Uten fungerende lag 1 er det vanskelig å teste de øvre lag.

Skal jeg blokkere i l1_connect?

Kommentarer i prekoden nevner to forskjellige måter å implementere l1_connect() på:

  • Blokkere i l1_connect() helt til tilkoblingen er ferdig. Da må du feks. lage din egen select()-løkke i l1_connect().
  • Sende connect-pakke, markere tilkoblingen som connecting og la l1_handle_events() gjøre noe smart med up-pakker som kommer tilbake.

Hint: sistnevnte kan være en bedre løsning.

Skal jeg implementere oppdeling av rammer/pakker/filer?

Det er ikke behov for å støtte oppdeling (fragmentering) av rammer eller pakker på lag 2–3. For å overføre større filer kan lag 5 dele opp sendingen i flere små biter.

Skal jeg implementere feildeteksjon (checksum o.l.)?

Du kan anta at alle mottatte UDP-pakker er fri for korrupsjon. Det er dermed ikke nødvendig å benytte en checksum på lag 2 slik som Ethernet gjør. UDP-pakker kan imidlertid gå tapt i sin helhet – dette må du ta høyde for.

Hva er portene som gis til l4_send()?

Det er portene som lag 4 i teorien kan bruke til å skille tjenester, slik at du skal kunne ha flere lag 5-programmer. Du behøver ikke skrive kode som sjekker disse portene, og kan derfor trygt angi 0 som begge portene til l4_send(). Portene på lag 4 må iallfall være under 1024 i prekoden.

Her skal du ikke bruke port angitt på kommandolinjen når du starter programmet.

Hjemmeeksamen 1

Må jeg ta hensyn til dupliserte rammer i nettverk med løkker?

I visse topologier med løkker kan man få dupliserte rammer hos endemottakeren når man bruker flooding for sending/videresending. Det er ikke nødvendig å ta hensyn til dette.

Husk: I denne oppgaven er det ikke noe krav om pålitelig ende-til-ende-kommunikasjon, kun punkt-til-punkt.

Hvor er l2_configbuf(), og hva trenger jeg den til?

Dere finner en eksempelsignatur i prekoden til den obligatoriske oppgaven som kan kopieres inn. Funksjonen l2_configbuf() skal kunne justere bufferstørrelsen (og dermed vindusstørrelsen) til et glidende vindu. Husk på å oppdatere informasjonen alle steder det er viktig å ha riktig vindusstørrelse.

Er det noen spesielle regler rundt ACKs?

Det er nyanseforskjeller i meningsinnholdet til ACKs i forskjellige ARQ-implementasjoner (Stop-and-Wait, Go Back-N, Selective Repeat). Følg som utgangspunkt ACK-mønstrene slik de er presentert i forelesningene. Det er ikke påkrevd å benytte NAKs.

Underkapittelet i læreboka (kap. 3.4, s. 226) dekker de fleste problemstillinger i forbindelse med Sliding Window-protokoller.

Generelt vil man aldri få trekk for å utbedre og gjøre optimaliseringer utover minimumskravene som er spesifisert i oppgaven. Alle avvik fra den opprinnelige oppgaveteksten skal begrunnes og dokumenteres i designdokumentet.

Hjemmeeksamen 2

Må jeg ha køer på lag 3?

Siden vi ikke har noe funksjonalitet på lag 4 i denne oppgaven, skal lag 3 tilby pålitelig ende-til-ende-kommunikasjon til lag 4 (slik som det står i oppgaven). Det betyr med andre ord at lag 3 på avsendernoden må mellomlagre de pakkene som blir sendt inntil det med sikkerhet kan si at pakkene har kommet helt frem til mottakernoden. Det er opp til deg å velge en passende mekanisme for å løse dette problemet, og implementere den på lag 3.

NB: Dette er annerledes enn i Internett-modellen! IP (på nettlaget) tilbyr ende-til-ende-kommunikasjon, men gir ingen garantier om pålietlighet. TCP er der eksempel på en transportlagsprotokoll som sikrer pålitelig overføring.

C-programmering

Hvordan fungerer…

En essensiell ressurs i C-programmering er de såkalte man-sidene. Du behøver neppe pugge disse, men bruk gjerne tid på å lære deg å lese man-sider. De har som regel alt du trenger å vite om en funksjon – en kort beskrivelse, parametre, returverdi og evt. hensyn man bør ta.

For å finne man-siden til funksjonen getaddrinfo, kan du kjøre følgende kommando i et shell: man getaddrinfo. Merk for øvrig at man-sidene finnes på Internett, se lenke til høyre.

Hvordan bør jeg skrive ut debuginformasjon?

Når du kompilerer koden med make debug vil gcc bli kjørt med opsjonen -DDEBUG. Dette kan du bruke til å kun printe debugoutput hvis programmet blir kompilert med make debug.

Her er et eksempel på en makro DPRINT() som fungerer som printf(), som også vil skrive ut filnavn og linjenummer, men ikke skrive ut noe hvis du kompilerer uten -DDEBUG.

#ifdef DEBUG
#define DPRINT(args...) fprintf(stderr,"%10s:%-3d - ", __FILE__, __LINE__); fprintf(stderr, args);
#else
#define DPRINT(args...)
#endif

Merk at du kan utvide en slik makro med tilleggsinformasjon etter behov. Se feks. en debugmakro som har tidspunkt med på utskriften.

Programmet mitt segfaulter?!
  • Sørg for at du kompilerer med flagget -g til gcc, hvis du ikke gjør dette så vil ikke debuggingsinformasjon bli lagt ved.
  • Kjør programmet ditt med gdb. Hvis du vanligvis ville kjørt ./main 1234 1, så gjør dette: gdb ./main, og når gdb har startet opp skriver du run 1234 1
  • Når programmet ditt da segfaulter, skriv bt full, da vil du se alle funksjonskallene (og argumentene til disse) som ledet opp til kræsjet, hvis du kun får opp spørsmålstegn så har du ødelagt stakken, da har du mest sannsynlig skrevet for mye til en variabel av typen char a[100];.

Terminologi

Norsk Engelsk  
Ramme Frame Overføres på lag 2
Pakke Packet Overføres på lag 3
  Payload Lasten fra/til laget over. (Typisk det som er igjen når header tas vekk.)

 

Av Kenneth K.J., Henrik B.
Publisert 10. feb. 2014 19:56 - Sist endret 15. juni 2014 22:10