Forum: PC-Programmierung Absicherung Kommunikation?


von Frank (Gast)


Lesenswert?

Hallo,

ich bastle an einem Kommunikationsprotokoll zwischen Clients und einem 
Server. Die Kommunikation erfolgt über UDP (kann nicht geändert werden). 
Da kann es vorkommen, dass Pakete verlorengehen oder beschädigt 
ankommen.
In einem Teil der Pakete werden Anweisungen zum Eintragen von Daten in 
in eine Datenbanken zum Server gesendet. Diese Pakete beantwortet der 
Server mit einer Quittung. Sollte eine solche Quittung beim Client nicht 
ankommen, kann das zwei Ursachen haben:

a) das ursprüngliche Paket ist beim Server nicht angekommen, also wird 
auch keine Quittung gesendet

b) die Quittung ist verlorengegangen

Der Client wartet immer eine gewisse Zeit auf die Quittung und sendet 
dann das ursprüngliche Paket evtl. nochmal. Im Falle, dass nur die 
Quittung verlorengegenagen ist, erfolgt dann aber die Eintragung in die 
Datenbank doppelt - sofern man keine zusätzliche Absicherung betreibt.

Um das zu verhindern gebe ich jedem Paket einen Timestamp mit, der im 
Falle einer Wiederholung unverändert bleibt und die Kennung, dass es 
sich um ein wiederholtes Paket handelt. So kann der Server nachsehen, ob 
er das Paket schon mal vor Kurzem verarbeitet hat.

Das funktioniert auch soweit ganz gut, ist aber ziemlich aufwändig, z.B. 
muss eine Liste der zuletzt verarbeiteten Pakete geführt werden. Hat 
hier evlt. jmd. noch einen Tip für einen celevereren Algorithmus? Danke.

Frank

von faustian (Gast)


Lesenswert?

"(kann nicht geändert werden)."

Das ist allerdings bloed, weil eigentlich willst du ein hoeheres 
RPC-Protokoll (DCE, ONCRPC, SOAP, whatever...) fuer so etwas nutzen.

von Tom M. (Gast)


Lesenswert?

Frank schrieb:
> Um das zu verhindern gebe ich jedem Paket einen Timestamp mit, der im
> Falle einer Wiederholung unverändert bleibt und die Kennung, dass es
> sich um ein wiederholtes Paket handelt. So kann der Server nachsehen, ob
> er das Paket schon mal vor Kurzem verarbeitet hat.
>
> Das funktioniert auch soweit ganz gut, ist aber ziemlich aufwändig, z.B.
> muss eine Liste der zuletzt verarbeiteten Pakete geführt werden. Hat
> hier evlt. jmd. noch einen Tip für einen celevereren Algorithmus? Danke.

Schau mal, wie es bei TCP gemacht wird, nämlich mittels Sequenz-Nummern. 
Wenn du dazu die Annahme machen kannst, dass sich Pakete niemals 
"überholen" oder das nur sehr wenige Pakete betrifft, scheint mir das 
viel effizienter zu sein, als mit Timestamps und Retransmit-Kennungen zu 
hantieren.

von Andreas F. (aferber)


Lesenswert?

Frank schrieb:
> Um das zu verhindern gebe ich jedem Paket einen Timestamp mit, der im
> Falle einer Wiederholung unverändert bleibt und die Kennung, dass es
> sich um ein wiederholtes Paket handelt. So kann der Server nachsehen, ob
> er das Paket schon mal vor Kurzem verarbeitet hat.

Das mit der expliziten Retransmit-Kennung als Signal "schau in der 
Liste" solltest du lassen, wenn die Kommunikation in einer nicht von dir 
selbst vollständig kontrollierten Umgebung erfolgt (und eigentlich 
nichtmal dann). Es kann vorkommen, dass Pakete bei der Übertragung 
verdoppelt werden, und das ist durchaus keine rein theoretische 
Möglichkeit, sondern das habe ich schon einige Male auch selbst real 
gesehen.

Mit Sequenznummern braucht sich der Empfänger keine Liste der letzten 
Pakete merken, sondern er muss nur die aktuelle Sequenznummer 
speichern. Er muss dann bei einem empfangenen Paket nur die Nummer des 
Paketes mit seiner eigenen aktuellen Nummer vergleichen:

- Ist sie kleiner oder gleich der eigenen, dann darf das Paket
  nicht erneut bearbeitet werden, es muss aber trotzdem ein ACK
  gesendet werden.
- Ist sie exakt eins grösser als die eigene, wird das Paket
  bearbeitet, ein ACK gesendet und die eigene Nummer um eins erhöht.
- Ist sie mehr als eins grösser als die eigene, wird das Paket
  einfach verworfen, der Sender sendet das dann ja später erneut,
  und bis dahin sind dann hoffentlich auch die fehlenden Pakete
  "dazwischen" eingetroffen.

Das Verwerfen von Paketen im letzten Fall oben führt zu suboptimalem 
Verhalten, wenn die Reihenfolge der Pakete unterwegs geändert wurde, da 
Pakete verworfen werden, die eigentlich korrekt angekommen sind. In sehr 
vielen Fällen tritt das in der Praxis aber nur selten auf, weshalb es 
meist nicht lohnt, den Zusatzaufwand dafür zu betreiben. Der Aufwand 
wäre im wesentlichen so hoch, dass man auch gleich TCP benutzen könnte.

Was du noch brauchst ist ein Synchronisationsmechanismus, mit dem am 
Anfang der Kommunikation (oder dann wenn zuviele Pakete zwischendurch 
verloren gehen, so dass der Sender irgendwann aufgibt) die 
Sequenznummern von Sender und Empfänger auf den gleichen Stand gebracht 
werden. Am besten schaust du dir dazu mal den Three-Way-Handshake von 
TCP an.

Andreas

von Andreas F. (aferber)


Lesenswert?

Ergänzung: auch für den Sender bringt dieses Sequenznummern-Verfahren in 
einigen Fällen eine Verringerung des Aufwandes mit sich.

Angenommen, das letzte ACK hatte die Nummer 4, die Zähler bei Sender und 
Empfänger stehen also beide auf 4. Jetzt werden die Pakete 5, 6, 7 und 8 
gesendet, vom Empfänger bearbeitet und geACKt, es gehen jedoch die ACKs 
5, 6 und 8 verloren.

Der Sender kann jetzt, wenn er das ACK 7 empfängt, nicht nur das Paket 7 
aus seiner Retransmit-Liste entfernen, sondern auch die Pakete 5 und 6, 
da er weiss, dass der Empfänger nur dann das ACK 7 senden würde, wenn er 
5 und 6 schon erfolgreich empfangen hat. Der Sender muss also nur das 
Paket 8 erneut senden.

Andreas

von Jochen F. (jamesy)


Lesenswert?

Wie wäre es mit einer Implementierung des AX-25-Protokolls?

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Danke für die Infos, ich werde mal versuchen, etwas draus zu machen. 
Sequenznummern klingen vernünftig. Allerdings muss ich die wohl für 
jeden Clienten einzeln führen, wenn es mehrere an einem Server sind.
Was mache ich bei Zähler-Überlauf (z.B. Integer mit 4 Byte)? Aber wenn 
der Server nach der gleichen Methode zählt, geht es ihm genau so und 
dann stimmts ja wieder ...

Frank

von U.R. Schmitt (Gast)


Lesenswert?

Frank Esselbach schrieb:
> Allerdings muss ich die wohl für
> jeden Clienten einzeln führen,

Sinnvollerweise behandelt ein Server jeden Client logisch getrennt in 
einer eigenen Session.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.