Der Modbus-TCP-Frame Byte für Byte: MBAP-Header und PDU

· Von Vladimir Chemeris, Entwickler von Modbus TCP FieldKit

Kurzantwort: Ein Modbus-TCP-Frame besteht aus einem 7 Byte langen MBAP-Header, gefolgt von einer PDU mit bis zu 253 Byte. Es gibt keine CRC, weil TCP die Integrität übernimmt. Alle mehrbytigen Felder sind Big-Endian.

Eine echte Anfrage

Wir haben drei Holding-Register von einem Server mit pymodbus 3.16.1 über einen Raw-Socket gelesen:

00 01 00 00 00 06 01 03 00 00 00 03
Bytes Feld Wert Bedeutung
00 01 Transaction-ID 1 Der Client wählt sie, und der Server wiederholt sie
00 00 Protocol-ID 0 Modbus verlangt 0
00 06 Länge 6 Folgende Bytes: Unit-ID plus PDU
01 Unit-ID 1 Weiterleitung hinter einem Gateway
03 Function 3 Read Holding Registers
00 00 Adresse 0 Erstes Register, 0-basiert
00 03 Anzahl 3 Drei Register

Alles bis einschließlich der Unit-ID ist der MBAP-Header. Der Function Code und alles danach bilden die PDU.

Die Antwort

00 01 00 00 00 09 01 03 06 00 64 00 FA 04 00
Bytes Feld Bedeutung
00 01 Transaction-ID Wie in der Anfrage
00 00 Protocol-ID 0
00 09 Länge 9 Bytes folgen
01 Unit-ID Zurückgegeben wie gesendet
03 Function Dieselbe Function, kein Fehler
06 Byte-Anzahl 6 Datenbytes
00 64 Register 0 100
00 FA Register 1 250
04 00 Register 2 1024

Wäre die Function fehlgeschlagen, enthielte die Antwort stattdessen 83 und einen Exception-Code.

Wofür jedes Header-Feld da ist

Transaction-ID. TCP kann Antworten ausliefern, nachdem der Client schon weitergegangen ist. Der Client ordnet jede Antwort anhand dieser Nummer ihrer Anfrage zu. Der Implementation Guide sagt, dass eine Antwort mit einer Transaction-ID, die zu keiner offenen Anfrage passt, „must be discarded“ (verworfen werden muss). Manche Gateways von RTU auf TCP geben 0 zurück, ein häufiger Grund, warum strenge Clients sich beschweren.

Protocol-ID. Modbus verlangt 0. Als wir hier einen Frame mit 00 01 gesendet haben, blieb pymodbus stumm, und der Client lief in den Timeout. Das ist ohne Mitschnitt schwer zu diagnostizieren.

Länge. Die Anzahl der Bytes nach diesem Feld. Ein Empfänger erkennt daran das Ende des Frames im TCP-Datenstrom. Ist sie falsch, verlieren Client und Server den Überblick, wo Frames beginnen.

Unit-ID. Wählt das Gerät hinter einem Gateway aus. Für ein Gerät direkt an TCP empfiehlt der Guide 0xFF und akzeptiert auch 0. Details und reales Verhalten.

Größenlimits

Das serielle Erbe setzt die Limits. Ein serieller Frame ist höchstens 256 Byte groß, davon bleiben 253 für die PDU. Mit dem 7 Byte langen MBAP-Header ergeben sich 260 Byte für TCP.

Daher stammen die bekannten Mengenlimits: Eine Leseantwort enthält höchstens 125 Register (250 Byte Daten, plus Function Code und Byte-Anzahl), ein Schreibzugriff auf mehrere Register höchstens 123 (die Anfrage trägt außerdem Adresse, Anzahl und Byte-Anzahl).

Vergleich mit RTU

Derselbe Lesezugriff als RTU-Frame ersetzt den Header durch eine Slave-Adresse und fügt eine CRC an:

01 03 00 00 00 03 05 CB

Es gibt keine Transaction-ID, Länge oder Protocol-ID, daher kann ein RTU-Master nur eine offene Anfrage auf der Leitung haben. RTU over TCP und Modbus TCP im Vergleich behandelt, was das bei Konvertern bedeutet.

Um Ihren eigenen Datenverkehr zu lesen, fügen Sie ihn in den Frame-Decoder ein.

Quellen

FAQ

Was ist der MBAP-Header?

Der 7 Byte lange Header, den Modbus TCP vor die PDU setzt: Transaction-ID (2 Byte), Protocol-ID (2), Länge (2) und Unit-ID (1). Er ersetzt Adresse und CRC eines seriellen RTU-Frames.

Hat Modbus TCP eine CRC?

Nein. TCP schützt die Daten bereits, daher hat der Modbus-TCP-Frame keine CRC. RTU-Frames tragen eine 2 Byte lange CRC, ebenso RTU over TCP.

Wie groß darf ein Modbus-TCP-Frame höchstens sein?

260 Byte: eine PDU von bis zu 253 Byte plus der 7 Byte lange MBAP-Header. Das Limit stammt vom ursprünglichen seriellen Frame mit 256 Byte.