Multiple Clients on One Modbus Gateway: Test Polling Latency and Timeout Isolation
Multiple TCP connections do not give one RS485 bus multiple simultaneous Modbus RTU transactions. A gateway can accept requests quickly while its serial queue falls behind. Capacity acceptance must therefore connect client deadlines to serial service time, transaction association, and failure isolation. This article provides a measurement plan and one labelled arithmetic example; it reports no measured gateway capacity.
Inventory Clients and Serial Workload
Create a workload entry for each client and request class: target port and unit, function code, start address, register count, polling period, burst pattern, and timeout/retry policy. Include engineering tools and local HMIs that may join during maintenance. A nominal “one-second poll” can become a synchronized burst when every client starts on the same clock boundary.
Separate direct forwarding from a gateway that polls devices itself and serves cached values. The latter can answer TCP quickly while returning old data. Specify acquisition timestamp, maximum permissible age, and behavior when collection fails. Also distinguish a display refresh target from a control deadline. Record serial format and device response variation from the actual device set; their model names alone cannot establish processing time.
Build the Serial Service-Time Budget
For each request, budget outbound wire time, device processing, inbound wire time, RS485 turnaround, and required frame-separation intervals. Add queue waiting and the cost of any retries separately. Use the Modbus Serial Line Guide V1.02 for the target RTU timing rules, and verify the implementation’s actual gap handling at the configured baud rate. A transparent bridge and a protocol-converting gateway need different framing assumptions.
Constructed calculation: a function-03 request for ten registers occupies 8 RTU bytes; its normal response occupies 25. At 19,200 bit/s with 8E1, each character has 11 transmitted bits. Wire time alone is (8 + 25) × 11 / 19,200, approximately 18.9 ms. This excludes processing, gaps, queuing, errors, and software overhead. It is a component estimate, not a polling-rate guarantee.
A first screening calculation is the sum of each arrival rate multiplied by its service time on the shared port. Approaching full utilization leaves little room for bursts or failures; even a value below one does not prove deadlines will hold. A silent device consumes its configured timeout and recovery interval instead of the normal successful-service estimate.
Verify Transaction Association
Log a correlation tuple containing connection generation, transaction identifier, target unit, serial port, function, and request sequence. The 16-bit Modbus transaction identifier is not globally unique across clients or across time. Two clients may legitimately use the same number. The gateway must retain enough context to send each response to the right requester, as described in the Modbus TCP implementation guide V1.0b.
Test repeated identifiers on separate connections, reconnect with identifier reuse, and a reply arriving after timeout. Serial RTU lacks the TCP transaction field, so a late reply can be ambiguous when similar requests follow each other. The design needs a bounded resynchronization or quarantine policy, using the device’s possible response timing; blindly assigning the next serial frame to the newest request is unsafe. If the device can respond arbitrarily late, document the remaining ambiguity rather than claiming perfect association.
Isolate Slow or Missing Devices
Make one serial device slow or silent while other clients continue their normal load. Measure the impact on healthy units on the same port and, separately, on another port. A shared serial bus necessarily loses time while an active request awaits timeout; isolation means bounding and containing that damage, not promising zero interference.
Review per-client queue limits, fair scheduling, request expiry, overload rejection, and reduced polling for persistently absent units. Check that expired queued reads do not waste bandwidth after their result is already useless. Separate ports may run concurrently, but a global worker or lock can still couple them. Moxa’s Modbus architecture guidance highlights serial queuing; the acceptance requirement must still be derived from the chosen product and workload.
Separate Read Polling from Write Recovery
For documented side-effect-free reads, recovery may mean skipping an obsolete sample and trying again at the next scheduled opportunity. Define how the host marks stale values. For a write whose reply is missing, the result may be unknown even if the gateway reports a timeout. Retrying an action can duplicate its physical effect; increasing retry counts is not a general reliability fix.
Coordinate host and gateway timeout budgets. If the host gives up before a queued request reaches serial, it may issue another request while the old one still executes. Prefer explicit expiry and cancellation semantics where supported. libmodbus’s response-timeout reference also distinguishes behavior when byte timeout is enabled or disabled. This article contains no library API example; verify those settings against the exact deployed release. Use the reconnect and unknown-command procedure for interrupted write recovery.
Define Load Steps and Boundary Cases
Start with one client and one healthy unit. Increase arrival rate, request size, and client count in separate steps before combining the declared production mix. At each step record sustained behavior, then add bursts, a missing unit, a high-rate client, and a reconnect. Exercise queue-full behavior and valid device exceptions. Run injections only on an isolated system authorized for testing.
| Test condition | Evidence to retain | Pass condition set before testing |
|---|---|---|
| Declared healthy workload | Per-class latency and queue depth | Every required deadline and freshness rule is met |
| One unit silent | Healthy-unit delay; timeout occupancy | Damage remains within the declared degraded-service budget |
| One client floods requests | Admission/rejection counts; fairness | Queue bounds hold and protected clients retain required service |
| Late reply after reconnect | TCP and serial correlation trace | No response crosses session or request ownership |
| Write reply lost | Device execution record; recovery log | Unknown outcome is surfaced; unsafe replay is prevented |
Report Capacity with Explicit Conditions
Report the supported workload as a set of conditions: hardware and firmware, ports, baud rates, device set, request mix, client behavior, and run duration. Present latency distributions, worst observed values, timeout rates, queue peaks, rejection counts, and data age. Include failed steps on the capacity curve; showing only the final successful point hides the overload boundary.
A worst observed delay is not a formal worst-case bound, and an average can hide deadline failures. Preserve raw traces, clock-alignment notes, and the exact traffic generator configuration so another engineer can reproduce the result. Recheck data interpretation using the register-mapping guide. To build a gateway acceptance plan, send Obeita the client refresh targets, serial device list, read/write mix, and degraded-service limits.
