Tipps zur Fehlersuche

Die Fehlersuche in Socket-Programmen unterscheidet sich nicht wirklich von der Fehlersuche in "normalen" Programmen. So lässt sich auch hier mit printf()-Aufrufen sichtbar machen, welche Programmteile in welcher Reihenfolge und mit welchen Parametern durchlaufen werden. Das alleine hilft oft schon sehr um das Programmverhalten zu verstehen. Weiterhin können Debugger wertvolle Einblicke liefern, verändern aber auch das Laufzeitverhalten erheblich, was insbesondere bei verteilten Systemen weitere Effekte verursachen kann (Timeouts etc.).

Typische Fehlerquellen

Zeilenumbrüche

Zeilentrenner sind oft plattformspezifisch. Manchmal hängen die verwendeten Trenner auch davon ab, ob Textdateien als Textdateien oder Binärdateien geöffnet wurden. Manche Terminal-Programme benutzen nur CR, andere CRLF als Trenner. Kurzum: oft ist es hilfreich, die Zeilenumbrüche sichtbar zu machen. Ich gebe Zeichenketten meistens in der Form "<%s>" aus, dann sieht man gleich ob und welche Art von unsichtbaren Zeichen enthalten sind.

Nullterminierung

Eher zu den Anfängerfehlern gehört das Vergessen der Nullterminierung ('\0') bei Zeichenketten. Die Socket-Funktionen arbeiten mit beliebigen Daten, d.h. sie treffen keinerlei Annahmen über den Inhalt. Daher muss man auch beim Senden von nullterminierten Zeichenketten eine Länge angeben, die im Fall von strlen() die Nullterminierung nicht mitzählt. Auf der Empfangsseite gibt die Länge der gelesenen Daten ebenfalls nur die Nutzdaten an, eine Nullterminierung muss selbst durchgeführt werden. Hier gilt es insbesondere daran zu denken, den Puffer ausreichend groß zu wählen, bzw. beim Aufruf von recv() entsprechend sizeof(buffer)-1 anzugeben, damit die '\0' noch rein geht.

Probleme mit select

Beim Einsatz von select() gibt es diese typischen Fehler:

Byte order

Mehrbytige Zahlenwerte werden immer in Network Byte Order angegeben. Vergisst man beispielsweise beim Einfüllen der Portnummer in eine sockaddr_in-Struktur (z.B. für bind() oder connect()) die Umwandlung mittels htons(), dann sieht die Portnummer komplett anders aus.

Tools

Sniffer

Wenn partout gar nichts funktioniert und man nicht mehr glaubt was man empfängt, dann sollte man mit einem Netzwerk-Sniffer prüfen, was tatsächlich auf der Leitung unterwegs ist. Für minimalistische Einsätze hat sich tcpdump als nützlich erwiesen, wenn es etwas komfortabler sein soll, dann bietet sich wireshark an. Wenn es weniger um den Inhalt der Kommunikation geht, sondern mehr darum, ob überhaupt etwas passiert, dann ist iptraf nützlich.

wireshark gibt es auch für Windows.

strace

Unter Linux gibt es das Tool strace das alle Systemaufrufe protokolliert, die ein Programm durchführt. Damit lässt sich schnell von außen sehen, an welcher Stelle ein Programm hängt oder beginnt sich merkwürdig zu verhalten. Allerdings ist die Ausgabe recht umfangreich, weil auch alle Bibliotheksfunktionen letztendlich Systemaufrufe tätigen und man sehr viele Dinge sieht, die man gar nicht bewusst ausgelöst hat.

Es gibt eine strace-Implementierung für Windows. Dort ist aber das Tool Process Monitor aus der Sysinternals-Suite empfehlenswerter.

netstat und ss

Das Dienstprogramm netstat gibt schnell Auskunft darüber, welche Verbindungen gerade aktiv sind. Mit der Option -A inet kann die Ausgabe auf Sockets der Familie AF_INET begrenzt werden (ansonsten sieht man meist jede Menge Sockets aus AF_UNIX). Per Default werden nur verbundene Sockets angegeben, durch die zusätzliche Option -a (all) oder -l (listen) können die Sockets im Listen-Zustand ebenfalls angezeigt werden.

Die Manpage zu netstat gibt an, dass dieses Programm inzwischen obsolet ist und ss es ablöst. netstat steht auch unter Windows zur Verfügung, hat dort aber teilweise andere Parameter.


Zurück zur Hauptseite