Sebastian Hempel bio photo

Sebastian Hempel

Software Crafter, Clean-Code-Developer, JEE Professional, Puppet-Master, OpenSource Fanboy, Alfisti

Email Twitter Google+ XING Instagram Github

In einem Projekt wurde ich vor kurzem zu Hilfe gerufen, um Probleme bei der Kommunikation eines PCs mit einem Gerät zu analysieren und zu beheben.

Vom PC wurde eine TCP/IP-Verbindung zum Gerät aufgebaut. Über diese Verbindung werden pro Verarbeitungsschritt des Geräts zwei Telegramme vom PC gesendet. Im ersten Telegramm erhält das Gerät Informationen über die Struktur der im zweiten Telegramm übertragenen Daten. Das Gerät beginnt nach dem Empfang der Daten mit deren Verarbeitung. Ist das Gerät mit dieser Aufgabe fertig, wird an den PC ein Telegramm gesendet, dass das Gerät jetzt wieder bereit für den Empfang neuer Daten ist.

Fehlerhafte Kommunikation ohne Handshake

Zwischen der Erfolgsmeldung des Geräts und dem Senden von neuen Telegrammen durch den PC kann nun eine gewisse Zeit vergehen. Im konkreten Fall wurde in dieser Zeit das Gerät aufgrund eines Problems mit der Hardware neu gestartet. Der PC hat von alledem nichts mitbekommen. Beim Senden des nächsten Telegramms mit den Strukturinformationen erkennt der TCP/IP-Stack des PCs, dass die Verbindung nicht mehr besteht. Die Verbindung wird neu aufgebaut. Aufgrund der Struktur der PC Software hat diese aber die zu sendenden Daten bereits verworfen und kann keinen zweiten Versuch unternehmen. Der nächste Verarbeitungsschritt des Geräts schlägt fehl. Der Fehler muss auf einer höheren Ebene der Software behandelt werden (= erneute Ausführung des Verarbeitungsschritts).

Was ist zu tun? Eine Umstrukturierung der PC Software ist nur schwer möglich. Theoretisch hätte man nach dem Senden des Telegramms eine gewisse Zeit warten können, ob eine getrennte Verbindung erkannt wird. In diesem Fall hätte man das noch nicht verworfene Paket erneut senden können. Im Falle einer erfolgreichen Übertragung des Telegramms, hätte man aber “nutzlos” eine gewisse Zeit gewartet. Die Performance der Kommunikation wäre massiv eingebrochen.

Verhalten mit Handshake

Die Lösung war die Erweiterung des Kommunikationsprotokolls um ein Handshake-Verfahren.

Das Gerät sendet nun nach dem Telegramm, dass vom PC an das Gerät übertragen wird (Request), eine Antwort (Response) zurück. In dieser Response signalisiert das Gerät über ein Flag, ob die empfangenen Daten korrekt sind und das Gerät damit weiter arbeiten kann (true) oder ob das Gerät zwar Daten empfangen hat, diese aber nicht für die weitere Verarbeitung geeignet sind (false).

Der PC wartet nach dem Senden des Telegramms eine definierte Zeit auf das Eintreffen der Response. Im Falle einer erfolgreichen Übertragung wird vom Gerät in relativ kurzer Zeit diese Response gesendet und der PC kann mit der weiteren Verarbeitung fortfahren. Im Falle eines Fehlers (= Timeout) empfängt der PC kein Response vom Gerät und kann dann entsprechend darauf reagieren - die Verbindung neu aufbauen.

Jetzt fällt die Wartezeit nur dann an, wenn es wirklich zu einem Fehler in der Kommunikation gekommen ist.

Handshake lohnt sich

Sicherlich ist die Implementierung einer Kommunikation mit Handshake aufwendiger. Nach dem Senden muss auf den Empfang der Response gewartet werden. Um nicht die gesamte Applikation zu blockieren muss nun auf jeden Fall, die Kommunikation in einen eigenen Thread ausgelagert werden.

Die Mühe lohnt sich aber auf jeden Fall, weil nur so eine fehlertolerante Kommunikation zwischen zwei Kommunikationspartner implementiert werden kann.