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
- Modbus Application Protocol Specification V1.1b3, Abschnitt 4.1
- Modbus Messaging on TCP/IP Implementation Guide V1.0b, Abschnitte 3.1 und 4.4
- Frames aufgezeichnet am 30. Oktober 2026 von pymodbus 3.16.1 unter Linux
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.