11.11 Der Puffer
Sockets zeigen in Verbindung mit den Funktionen read() und write() häufig ein (wer es noch nicht kennt) seltsames Verhalten, das sich von der normalen Datei-I/O dieser Funktionen unterscheidet. Mit read() und write() können bei den Sockets erst einmal weniger Bytes ein- bzw. ausgegeben werden wie angenommen. Das Problem ist, dass der Kernel für das Socket eine bestimmte Puffergröße vorgibt. Das bedeutet, wenn der Puffer voll ist, liest read() bzw. schreibt write() aus diesem bzw. in diesen Puffer – selbst wenn noch nicht alle gewünschten Daten ausgelesen bzw. geschrieben wurden.
Wie Sie sicher wissen, übernimmt bei den Standard-C-Funktionen wie fgets(), fputs() ... das System die Aufgabe der Pufferung. Sie mussten sich nie selbst darum kümmern. Bei den elementaren Funktionen wie read() oder write() müssen Sie sich selbst darum kümmern.
Welche Puffergröße Sie hierfür verwenden, bleibt Ihnen überlassen und kommt auch auf den Anwendungsfall an. Allerdings macht ein byteweiser Puffer genauso wenig Sinn wie ein überdimensional großer Puffer. Es hat sich bewährt, eine Puffergröße von 512 oder 1024 KB zu verwenden. Selbiges gilt natürlich auch für send() und recv(), sofern diese Funktionen nicht mit dem Flag MSG_WAITALL aufgerufen werden.
Solange Sie Daten in Form eines char-Arrays mit einfachem Text übertragen, dürften Sie keine Probleme mit der Pufferung bekommen, sofern Sie einen String ordentlich mit \0 abschließen. Was ist aber, wenn Sie binäre Dateien übertragen wollen? Hier ist oft der Hund begraben – denn bei binären Dateien können Sie sich nicht darauf verlassen, dass diese Datei mit \0 abgeschlossen wird. In solch einem Fall müssen Sie sich selbst um das letzte Zeichen kümmern. Daher wurde ja schon im ersten Beispiel der Socket-Programmierung folgendes Konstrukt verwendet:
size = recv(create_socket, buffer, BUF-1, 0);
if( size > 0)
buffer[size] = '\0';
Der Puffer ist Ihr wichtigstes Kommunikationswerkzeug, mit dem Sie Daten austauschen können. Sie sollten daher immer bedenken, wenn Sie etwas darin hineinschreiben, wie dies auf der anderen Seite wieder herauskommt, und eventuell auch überprüfen, was herauskommt. Denn wenn häufig etwas nicht klappt, dann ist es die Art und Weise, wie die Daten beim Empfänger ankommen. Nicht selten ist es ein nicht terminierter String, der für Zeichensalat sorgt.
|