Hantera inkommande data i en socket

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Aug 2003

Hantera inkommande data i en socket

Jag håller på att lära mig nätverksprogrammering och har gjort en enkel klient och server som är tänkt att användas som en enkel spel-server. Jag har gjort ett enkelt protokoll som har en header med en byte som anger vad det är för typ av meddelande (chat-meddelande, information om andra spelare, etc.) och två bytes som anger längden för det efterföljande meddelandet. I det ideala fallet när varje meddelande är så långt som det påstår och alla meddelanden kommer fram hela borde detta funka bra men vad ska jag göra om något går snett?

Tänk att ett meddelande påstår att det är 100 bytes långt men det bara finns 60 bytes att läsa från nätverksströmmen. Antingen är headern felaktig pga störningar i nätverket eller en bugg i klienten, eller så har den sista biten inte kommit fram ännu och kan jag i så fall lita på att den kommer? Om den kommer, kan jag då lita på att den kommer innan något annat meddelande?

Om det istället skulle finnas mer data att läsa i bufferten än meddelandets längd skulle det kunna vara fel i headern eller att två meddelanden har inkommit samtidigt. Om det är två meddelanden är det bara att läsa så långt det första meddelandet sträcker sig och spara det andra meddelandet i bufferten till senare. Ifall det skulle vara ett fel i headern så kommer istället skräpdata från det första meddelandet att ligga kvar i bufferten och tolkas som en header vid nästa avläsning.

Jag skulle ju kunna lägga en signatur först i headern för att skilja den från skräpdata och använda en checksum för att veta att headern och meddelandet är korrekt men det finns kanske något annat sätt att göra det på.

Finns det några bra sidor/böcker att läsa om detta ämne?

I don't want to be human! I want to see gamma rays! I want to hear X-rays! And I want to - I want to smell dark matter!

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Mar 2005

Det vanligaste sättet att skydda sig mot korrupta paket är som sagt att inkludera en checksumma i själva paketet. Den vanligaste och enklaste metoden är att helt enkelt bifoga en crc32-checksumma efter paketet som mottagaren får jämföra med.
Detta skyddar ju som sagt bara mot störningar och inte mot att någon injectar egna paketet i dataströmmen.
Mer säkrare protokoll som SSH använder en HMAC (keyed-Hash Message Authentication Code) för att verifiera att alla paket verkligen kommer ifrån rätt avsändare, men detta är nog overkill för ett spel.

När man väl fått ett korrekt paket så måste man fortfarande validera så att innehållet är korrekt för att undvika säkerhetshål.

När det kommer till att läsa själva datan ifrån socketen så kan man bestämma en timeout, om inte klienten skickat hela paketet inom denna period så kan man helt enkelt stänga ner anslutningen.

Ifall man skickar informationen över en dataström (TCP) och inte över enskilda paket (UDP) så bör man stänga ner anslutningen så fort man upptäcker något fel i dataströmmen.

Intel Core i7-3770K | NVIDIA Geforce GTX 980 | 16 GB DDR3 | DELL P2415Q | DELL U2711 | DELL U2410

Trädvy Permalänk
Medlem
Plats
Malmö
Registrerad
Okt 2001

Om du använder TCP så behöver du inte bry dig så mycket om sånt här. Det är operativsystemets ansvar att se till att paketen kommer i rätt ordning och att alla paket kommer fram (paket skickas om om dom inte kommer fram). TCP har också redan en inbyggd checksum som kollar så att inget blivit fel i paketen.

Nu kan saker och ting naturligtvis gå fel ändå men i praktiken behöver man inte bry sig om det.

Det enklaste sättet att skydda sig mot fel i klienterna så som att "header" längden" är fel är att dels sätta rimliga gränser för hur stor/liten den kan vara. Rimligt kanske är att längden på ett meddelande är mellan 0 och 10000. Dels ha timeouts i din kod, alltså om inget skickats de närmaste 10 sekunderna stäng anslutningen.

Om du istället använder UDP (vilket du borde om du programmerar spel) så är allt mycket svårare. Om du vill läsa hur man löst dessa problement i quake 3 så står det lite om det här
http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Net...