Gå til innhold

[Løst] [python] kjappt spm. om recvfrom (udp sockets)


Anbefalte innlegg

La meg bare nevne at jeg kun har holdt på med Python i ett par mnd, så jeg er ikke så veldig kjent med språket.

 

 

Saken er at jeg har noe kode som kjører en UDP-server, og noe annen kode som kjører UDP-klient.

 

Saken er at slik jeg har fortsått det så må man definere buffer size når man gjør en recvfrom på serveren. Men hva gjør jeg hvis jeg ikke vet hvor mye data som skal mottas (dette vil variere veldig)?

 

Jeg slet lenge med en "bug" som viste seg å være at serveren ikke mottok all data pga. for lav buffer size.

 

Det virker litt uprofft å sette denne latterlig høy for å være sikker på at jeg mottar all data?

 

Noen tips?

Lenke til kommentar
Videoannonse
Annonse

Det er ikke ofte jeg har gjort noe så low level socket greier, men det jeg tror er den vanlige strategien er at du må dele opp meldinger som er større enn bufferstørrelsen. Hvis du avsluter alle meldinger på en bestemt måte, f.eks. ved å sende "EOF" som det siste du gjør, vil mottakeren kunne vite om han har lest hele meldingen, eller om han må lese mer.

Lenke til kommentar

Det var jo ikke en så gal tanke.. men med UDP så vet man jo ikke om meldingen kommer fram eller ikke. Så hvis jeg deler meldingen opp i f.eks. 3 deler, men så kommer bare del 1 og del 3 fram så tror mottakeren at alt er kommet fram, mens man egentlig har korrupte data.

 

Og da må man jo fort legge til noen mekanisme for å si ifra hvor mange deler man har.

 

Også skal de settes sammen i en bestemt rekkefølge...

 

Blir for kompliserte greier.

Endret av xibriz
Lenke til kommentar

Dette er ikke støttet av UDP, og du burde vurdere å enten skrive om programmet ditt til å ikke ha disse kravene. F.eks. ved at ting som må henge sammen alltid er 1 pakke. Du har en maksimal størrelse på 65,507 bytes per pakke, noe som burde være mer enn nok til det meste.

Lenke til kommentar

I så fall kan du se etter andre måter å skrive om koden din på slik at ting sendes i mindre porsjoner, hvor det fortsatt ikke er farlig om enkelte deler forsvinner eller kommer i feil rekkefølge.

 

Et annet spørsmål er jo, hvorfor ikke bruke TCP?

Lenke til kommentar

Det skalerer ikke med TCP. Jeg lager en orm som skal kunne infisere opp mot 2048 maskiner og alle skal vite om alle andre.

 

Når det skal sendes informasjon om plassering, sortering, status ++ på alle kjente maskiner til alle andre så kan det ikke brukes TCP.

 

Og informasjonen må flyte fort.

Lenke til kommentar

Nå kan ikke jeg python, men kan du ikke bare prefixe meldingen med en lengde, f.eks hvis pakken er text formatert "0028Dette er data i pakken og den er så lang".

 

altså: <hex-lengde><data>

 

Dersom pakkelengden overstiger 576 bytes, ender du dog opp i en litt annen situasjon. Selv om UDP teoretisk sett støtter en max størrelse på 65507 bytes, er det få protokollimplementeringer som støtter dette. Den gjengse oppfatningen er at man bør holde seg til opp til 512 bytes pakker (pga reassembly size). Hvis man overstiger dette bør man selv splitte pakkene i flere pakker og lage til sekvensnummer og håndtering dersom pakker kommer i feil rekkefølge, eller dersom man mottar pakke 2 og 3 men ikke 1 osv. Dette kan fort ende med at man prøver å implementere noe som til slutt ligner på tcp, men som mest sansynlig er upålitelig og ikke spesiellt effektivt.

 

Så spørsmålet blir er det virkelig nødvendig med pakker over 512 bytes? Hva med å splitte hver pakke i typer - f.eks la oss si du skal overføre 3 biter med informasjon som totalt sett har en lengde på x bytes - send først pakke 1 med format <pakke-type><data> så pakke 2 på samme format osv - ergo:

 

01Dette er data for pakketype 1

02Dette er data for pakketype 2

03Dette er data for pakketype 3

 

Siden tanken her er at man ikke sender pakker over 512 bytes, kan man kutte ut lengde-spesifikasjonen i pakken. UDP garanterer at dersom man får pakken, er den komplett. Man parser så de to første bytene for å se hvilken pakketype det er og så lagrer denne informasjonen.

 

Dersom du da mister pakke med type 2 må applikasjonen klare seg uten denne informasjonen frem til den evt. blir sendt på ny.

 

En annen metode er at hver node sender ut sin tilstedeværelse på nettverket, og at alle andre noder connecter til denne noden via tcp for å hente ned informasjon, dette kan dog være betraktelig tregere men kommer ann på hvor ofte en node broadcaster informasjon om seg selv, og hvordan. Man kan tenke seg at broadcast pakken inneholder en id. Denne id'en endrer seg kun dersom endringer for den noden skjer og at de som allerede har data om denne noden slipper å koble seg opp med mindre id'en noden sender er anderledes enn den som er lagret. Denne broadcastpakken kan så f.eks inneholde id'en og tcp-porten man skal connecte til.

Endret av oelbox
Lenke til kommentar

Er det rett at dette returnerer antall bytes i ett pickle objekt?

print len(pickle.dumps(testArray, -1))

 

Dersom jeg oppfattet problemstillingen rett, er svaret her "dette er uvesentlig". Du ønsker ikke å velge pickle som representasjon av data-over-ikkekryptert-forbindelse.

 

Det til side, *må* det være 1 UDP-pakke? Hvorfor ikke flere? En veldig enkel måte å sjekke at du har fått "alt" i riktig rekkefølge er å la den første pakken inneholde lengde og sjekksum på den egentlige meldingen. Deretter venter man X antall sekunder og hvis man ikke har fått riktig antall bytes i pakkene eller de pakkene som er ankommet har en annen sjekksum, antar man at meldingen er tapt.

Endret av zotbar1234
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...