Protocols

Modbus TCP

By CourseTron Team ·  7 min read ·  Updated Oct 2026 💬 𝕏 in f
Table of Contents
    ? Print / Save as PDF

    In short: Modbus TCP wraps the classic Modbus request/response PDU in a 7-byte MBAP header and sends it over TCP port 502, dropping the CRC (TCP and Ethernet already protect the frame) and reusing the unit ID so a gateway can steer the request to a specific RTU slave on a serial line.

    Why Modbus TCP exists

    Modbus RTU was designed in 1979 for RS-485 multidrop wiring: one master, up to 247 slaves, every frame guarded by a 16-bit CRC and delimited by silent gaps of 3.5 character times. That works well on a 9600 or 19200 baud bus, but plants wanted PLCs, SCADA servers and HMIs on Ethernet. Rather than invent a new application layer, Schneider (the Modbus owner) kept the function codes and data model intact and defined a new transport mapping: Modbus TCP. If you already understand the differences between Modbus RTU and TCP, this article goes one layer deeper into the byte-level framing and gateway behaviour that interviewers love to probe.

    Key fact: the Modbus PDU (function code + data) is identical in RTU and TCP. Only the wrapper, the "ADU", changes.

    The MBAP header, byte by byte

    The Modbus Application Protocol header is exactly 7 bytes, all multi-byte fields big-endian:

    • Transaction ID (2 bytes): chosen by the client, echoed unchanged by the server. It lets a client keep several requests in flight and match replies.
    • Protocol ID (2 bytes): always 0x0000 for Modbus. Receivers should reject anything else.
    • Length (2 bytes): count of the bytes that follow, i.e. unit ID + function code + data.
    • Unit ID (1 byte): the addressing byte inherited from the RTU slave address.
    Modbus TCP ADU = MBAP header (7 B) + PDU Transaction ID2 bytes Protocol ID2 B = 0x0000 Length2 bytes Unit ID1 byte Function1 byte Data0 to 252 bytes MBAP header (first 6 B are fixed framing) Length field counts from here to the end No CRC field: TCP checksum + Ethernet FCS do that job. CourseTron · coursetron.com
    Frame layout of a Modbus TCP message. The maximum ADU is 7 + 253 = 260 bytes.

    A worked example you can decode by hand

    Read 10 holding registers starting at address 0x006B from unit 0x11 (function 0x03):

    Request : 00 01 | 00 00 | 00 06 | 11 | 03 | 00 6B | 00 0A
              txn=1   proto=0  len=6  unit fc   addr    qty=10
    Response: 00 01 | 00 00 | 00 17 | 11 | 03 | 14 | 20 bytes of register data

    Check the lengths: the request carries unit (1) + function (1) + address (2) + quantity (2) = 6. The response carries unit (1) + function (1) + byte count (1) + 20 data bytes = 23 = 0x17. Interviewers like to ask "what does the length field include?" and the common wrong answer is "the whole frame". It excludes the first six header bytes.

    Key fact: an exception reply sets the top bit of the function code (0x03 becomes 0x83) followed by a one-byte exception code, so the length is 3.

    Port 502 and the client/server model

    A Modbus TCP server listens on well-known port 502 (IANA registered; secure Modbus/TLS uses 802). The master/slave vocabulary becomes client/server: the client opens a TCP connection, sends a request, and the server replies. Because TCP is a byte stream, the receiver must not rely on packet boundaries. Parse the first six bytes, read the length, then read exactly that many more bytes. Production code in libmodbus or pymodbus does precisely this. Embedded servers commonly cap concurrent connections at 4 to 16, so a SCADA server polling carelessly can starve an engineering laptop out of a PLC.

    Pipelining is allowed by the transaction ID, but many cheap devices process one request at a time, so conservative clients keep a single request outstanding per connection and use a timeout of a few hundred milliseconds.

    Why there is no CRC

    RTU needs its CRC-16 because a noisy RS-485 line has no other integrity check. On Ethernet, every frame already ends with a 32-bit FCS checked by the NIC, and TCP adds a 16-bit checksum plus retransmission and ordering. A Modbus CRC on top would be redundant overhead. The trade-off: TCP guarantees the bytes arrive intact, but not that the application is sane. Also note that silent-interval framing (the 3.5 character gap) disappears entirely, replaced by the length field.

    PropertyModbus RTUModbus TCP
    TransportRS-485 / RS-232TCP, port 502
    AddressingSlave address 1-247IP address + unit ID
    IntegrityCRC-16TCP checksum + Ethernet FCS
    Framing3.5-char silenceMBAP length field
    Max frame256 bytes260 bytes
    Matching repliesStrict one at a timeTransaction ID

    Unit ID and how gateways bridge to RTU

    When you talk to a native TCP device, the unit ID is mostly irrelevant; many devices ignore it or expect 0xFF (or 0x01). It becomes essential at a gateway, where one IP address fronts a whole RS-485 bus. The unit ID then is the RTU slave address.

    Gateway: Modbus TCP to Modbus RTU SCADA client192.168.1.10 Gateway 1. strip MBAP, keep txn ID 2. unit ID becomes address 3. append CRC-16 Slave 17 (meter) Slave 18 (drive) Slave 19 (VFD) TCP :502 RS-485 CourseTron · coursetron.com
    One IP address, many serial slaves: the unit ID selects the target on the RS-485 bus.

    The gateway algorithm is straightforward:

    • Accept the TCP request and remember the transaction ID.
    • Drop the MBAP, take the unit ID as the RTU address, keep the PDU, and compute and append CRC-16 (polynomial 0xA001 reflected).
    • Transmit on the serial line, honouring the inter-frame silence, and start a response timer (often 500 ms to 1 s at low baud rates).
    • On a valid reply, check the CRC, strip it, and prepend a fresh MBAP with the stored transaction ID and the correct length.
    • On timeout, return exception 0x0B (gateway target device failed to respond); if the serial path is unusable, 0x0A.

    Because the serial bus is half-duplex, the gateway queues requests and serializes them. A burst of 20 clients each polling 10 devices at 9600 baud, with each transaction taking roughly 30 to 60 ms, will saturate the line. This is why gateway throughput, not Ethernet bandwidth, is the usual bottleneck. Broadcast requests (RTU address 0) get no response, so the gateway should reply immediately or after the bus quiet time.

    Key fact: the CRC is created and destroyed at the gateway. It never crosses the Ethernet side, and the transaction ID never crosses the serial side.

    Watching it move

    Request out, response back Client Server :502 REQ #1 RSP #1 Same transaction ID in both directions CourseTron · coursetron.com
    Animation: the client sends a request, the server echoes the transaction ID in the response.

    Practical pitfalls and security

    • No authentication or encryption: anyone who reaches port 502 can write coils. Segment the network, firewall 502, or use Modbus/TLS on 802. This is a classic ICS security interview topic.
    • Address off-by-one: documentation says register 40001 but the wire address is 0.
    • Byte and word order: 32-bit floats span two registers and vendors disagree on the word order.
    • Stale connections: use TCP keepalive and reconnect logic, since many PLCs silently drop idle sockets.

    The same protocol knowledge underpins SoC debug and test infrastructure, such as the board-management controllers and test-rig automation that the engineers at Avecas design services build around silicon bring-up. For a comparison with a bus built for deterministic realtime, read CAN bus basics.

    Want hands-on practice with industrial and embedded protocols? Explore the CourseTron courses and learn by building. For instructor-led VLSI training, see ChipXpert.

    FAQ

    What port does Modbus TCP use?

    TCP port 502 for standard Modbus TCP, and port 802 for Modbus/TLS (Modbus Security).

    Why does Modbus TCP not have a CRC?

    Ethernet already appends a 32-bit FCS and TCP adds its own checksum with retransmission, so the 16-bit Modbus CRC would be redundant.

    What is the unit ID used for?

    It carries the RTU slave address. A gateway uses it to choose which serial device receives the request; native TCP devices often ignore it or expect 0xFF.

    How does a gateway convert Modbus TCP to RTU?

    It strips the MBAP header, saves the transaction ID, uses the unit ID as the slave address, appends a CRC-16, transmits serially, then reverses the process on the reply.

    Advertisement