Serial-to-TCP Gateway Won’t Reconnect? Check Stale Sessions, Buffers and Duplicate Commands

A serial-to-TCP gateway that accepts a new connection has recovered only its transport. The old session may still own a serial port, a partial frame may remain in a buffer, or a command may already have executed without its reply reaching the client. Diagnose reconnect failures by following session ownership and message outcomes across both interfaces. The procedure below is intended for an isolated test bench; it does not promise lossless or exactly-once command execution.

Locate the Stale Session

First identify which side opens the connection and which side listens. Record any single-client restriction, exclusive serial ownership, and limits on simultaneous sessions. Capture the client’s socket state, the gateway’s session list, and the last completed application exchange. A server that still reserves its only slot for an unreachable client can look unavailable even while its Ethernet interface responds normally.

Distinguish an orderly close, an application crash, a host power loss, a broken route, and a gateway reboot. An operating system may close sockets when a process exits; an unreachable host cannot always send that notification. A cable pull is therefore only one failure case. On both endpoints, retain timestamps for the last received byte, last valid frame, last confirmed command, and session creation. These events answer different questions and should not share a single “last seen” variable.

Separate Transport Liveness from Application Progress

A TCP acknowledgment confirms transport-level receipt, not that a serial device executed an action. Keepalive probes can help detect an unreachable peer on an otherwise idle connection. Retransmission or user-timeout policies address different states, such as data remaining unacknowledged. Available controls and their interaction depend on the operating system or gateway firmware; check the target implementation rather than copying a generic timeout recipe.

An application heartbeat is useful only for the scope it actually exercises. A reply from the network task can prove that task is responsive while the serial worker is stalled. Where the device protocol permits it, a safe request routed through the actual serial path provides stronger evidence. RFC 9293, sections 3.8.3 and 3.8.4 separates connection-failure behavior from optional keepalive processing. Set the permitted detection delay from the product’s recovery requirement, then verify it under expected network variation.

Define Bounded Session Cleanup

Define an explicit transition from active to suspect, closing, released, and eligible-for-reconnect. Closing must release application ownership as well as the socket: cancel pending timers, mark outstanding transactions, relinquish the serial reservation, and reclaim the connection slot. Use a session generation identifier so a delayed callback from the old session cannot close or modify a newly established one.

Use bounded retry delays with jitter when many clients may reconnect together, and reset the backoff only after meaningful stability. Moxa’s NPort reconnect FAQ illustrates how its TCP alive-check setting affects stale-session cleanup. Its setting names and defaults apply to the listed product families, not every serial gateway. Confirm what happens when detection is disabled and whether a manual reboot merely hides a resource leak.

Reconnect state flow separates stale-session cleanup, frame handling, and unknown command outcomes.
Original design diagram. A new connection is admitted only after old ownership and uncertain data are handled.

Check Stream Framing Across the Bridge

Treat every TCP read as an arbitrary chunk of a stream. Accumulate enough bytes to validate a protocol header, derive a bounded message length, and extract complete messages while retaining an incomplete tail. If the protocol uses delimiters, define escaping and maximum frame size. Reject invalid lengths before allocating large buffers. Silence-based serial framing requires a separate timing policy at the serial boundary.

On reconnect, do not automatically concatenate a previous session’s partial message with the new session’s first bytes. That can synthesize a command neither client intended. Reset parser state or resume only through an explicitly designed protocol mechanism. Test each byte boundary of a representative request, combined messages, malformed prefixes, and a close in mid-frame. For the architectural distinction between byte forwarding and protocol conversion, see the serial-device-server versus Modbus-gateway guide.

Specify Buffer Ownership During Reconnect

Give every buffered item an owner, direction, creation time, expiration rule, and outcome state. “Buffered” may mean received from TCP, queued for serial, partly transmitted, fully transmitted without a device reply, or awaiting delivery back to the client. Those states demand different recovery decisions. In particular, clearing a software queue cannot undo bytes already transmitted to an actuator.

Buffer ownership and reconnect decisions
State when connection fails Safe default to evaluate Acceptance condition
Partial inbound application frame Discard with reason No cross-session frame is constructed
Queued command not yet sent to serial Expire or require renewed authorization Old command cannot execute after its valid time
Serial write completed; reply missing Mark outcome unknown No automatic unsafe replay
Telemetry awaiting upload Apply documented retention policy Age, order, loss, and duplicates are observable

Bound each queue and define backpressure or rejection before memory is exhausted. Measure high-water marks under a slow receiving client. Offline telemetry can have a store-and-forward policy, covered separately in offline replay acceptance; that policy is not blanket permission to replay control commands.

Handle Commands with Unknown Outcomes

Classify operations by device semantics. A documented, side-effect-free read is usually a better retry candidate than a trigger command. Some reads clear status or consume queued data, so even “read” deserves checking. Setting a value may appear idempotent, yet a device can treat every write as an action. Starting a batch, incrementing a counter, and pulsing an output are obvious duplicate-execution risks.

When the reply is lost after execution, the client generally cannot infer success from the broken connection. Prefer a device-supported operation identifier, durable deduplication, or a reliable result query. Modbus transaction identifiers correlate exchanges; they are not a persistent exactly-once execution contract across reconnects. If the underlying device provides no way to resolve uncertainty, stop automatic replay and surface “outcome unknown” for the authorized recovery procedure. Also coordinate client and gateway retries so one logical request does not multiply at two layers.

Verify Recovery Beyond a New TCP Connection

Build a fault matrix covering a graceful close, client termination, host loss, one-way traffic blackhole, slow consumer, silent serial device, and repeated short interruptions. Use a simulator or safe load for anything with physical side effects. Observe both Ethernet and serial traffic, session generations, queue depth, discarded bytes, and command execution counts. Keep the fault trigger time on the same clock or document the clock alignment.

Before testing, state limits for detection, cleanup, and time to the first correct post-recovery exchange. Pass only when ownership is released, frames remain valid, buffer bounds hold, and uncertain commands follow policy. A successful TCP handshake alone is insufficient. Record firmware, settings, duration, repetitions, and untested paths rather than claiming universal recovery. For a real investigation, provide Obeita the gateway mode, reproducible disconnect sequence, paired socket/serial logs, and command side effects.

Similar Posts