XON and XOFF are two control characters that let a serial receiver tell a sender to pause and resume. That’s the whole idea behind software flow control. No handshake wires, no dedicated signals — just two bytes sent back up the same link the data travels on. When a device can’t keep up, it sends XOFF and the sender stops. When it’s ready again, it sends XON and the sender continues.
Table of Contents
The two characters
The scheme rests on two bytes from the ASCII control set — the DC, or device control, group:
| Name | ASCII | Hex | Decimal | Keyboard | Means |
|---|---|---|---|---|---|
| XON | DC1 | 0x11 | 17 | Ctrl-Q | Resume sending |
| XOFF | DC3 | 0x13 | 19 | Ctrl-S | Stop sending |
The mnemonic is transmit ON and transmit OFF. XOFF is the brake. XON lets go of it.
These codes came before RS-232 flow control. DC1 and DC3 originally switched a paper-tape reader on and off on old Teletype gear. The names carried over when the same two characters were reused to pace data on a serial line.
How the cycle works
Flow control here is driven by the receiver. It watches its own input buffer and steps through this loop:
- Data arrives faster than the receiver can handle it. The buffer starts to fill.
- When the buffer crosses a high mark, the receiver sends XOFF (0x13) out its transmit line to the far-end sender.
- The sender sees XOFF and stops sending data.
- The receiver works through its backlog. When the buffer drops below a low mark, it sends XON (0x11).
- The sender sees XON and picks up where it left off.
Each direction runs on its own. Side A can XOFF side B while side B keeps sending to A, and the other way around. Both ends can throttle each other independently.
Why three wires are enough
This is the part that surprises people coming from hardware flow control. XON and XOFF travel in-band — on the data lines themselves. Under ITU-T V.24 those lines are circuit 103 (transmitted data) and circuit 104 (received data), with circuit 102 as signal ground. That’s all the scheme touches. No request-to-send, no clear-to-send, no data-terminal-ready. The control characters ride the exact same path as the data.
Electrically, the two bytes are nothing special. They’re framed and sent like any other character, using the unbalanced double-current signaling defined in ITU-T V.28: a mark (binary 1) sits more negative than -3 V, a space (binary 0) more positive than +3 V, with the band between ±3 V treated as the transition region. Data rates stay below 20 kbit/s. XON and XOFF are just two particular bit patterns sent at those levels — the receiver watches the incoming byte stream for them.
Note the layer split here. V.24 and V.28 (and TIA/EIA-232-F) define the wires, the signals, and the voltages. They don’t define XON/XOFF. The flow-control behavior lives one level up, in what the two ends agree to do when they see 0x11 and 0x13. The standards give you the pipe; XON/XOFF is a convention for using it.
Because it only needs transmit, receive, and ground, XON/XOFF runs fine over a bare three-wire cable. For that wiring, see the three-wire version in Null Modem Cable Pinout.
The catch: two byte values are spoken for
Since the control characters live inside the data stream, the byte values 0x11 and 0x13 are reserved. If your actual data ever contains those bytes, the receiver reads them as flow control instead of data. The bytes vanish from the payload, and the link may stall waiting on a pause or resume that was never meant to happen.
For plain text this rarely bites. 0x11 and 0x13 aren’t characters you’d normally type or print, so a 7-bit ASCII stream sails through. Binary data is the problem. Firmware images, packed protocol frames, compressed files — anything 8-bit — will hit those values sooner or later. That’s the main reason binary transfers switch XON/XOFF off and lean on hardware flow control or a protocol that frames its own data.
You can work around it with an escape or literal-next scheme, but that adds overhead and both ends have to implement the same trick. For binary, the clean answer is simpler: don’t use XON/XOFF.
Reaction time
XON/XOFF is not instant, and treating it as if it were is a common way to lose bytes. When a receiver sends XOFF, several things are already in motion:
The XOFF byte has to travel back to the sender. The sender may have characters already sitting in its output buffer or in flight on the wire. And the sender’s software only notices the XOFF between bytes, not mid-character.
So data keeps arriving for a short window after XOFF goes out. If the receiver waits until its buffer is completely full before sending XOFF, that window overflows it and bytes are lost. The fix is headroom: send XOFF while there’s still room for whatever will land during the reaction gap. Terminal software and OS serial drivers handle this for you. On a custom device or your own firmware, the margin is your job.
XON/XOFF vs RTS/CTS
Two ways to pace a serial link, solving the same problem from different angles.
| XON/XOFF (software) | RTS/CTS (hardware) | |
|---|---|---|
| Signaling | Two bytes in the data stream | Dedicated wires (pins 7 and 8 on DB9) |
| Wires needed | 3 (TX, RX, GND) | TX, RX, GND plus RTS and CTS |
| Reaction | After the byte travels and is seen | Near-instant |
| 8-bit clean | No — 0x11 and 0x13 are reserved | Yes — passes every byte value |
| Works over | Any transparent path, including modems and radio | Links that actually carry the control wires |
| Both ends must match | Yes | Yes |
Rough rule: text and terminal traffic over a long or wire-limited path lean toward XON/XOFF. Binary data or high throughput, where you can run the extra conductors, lean toward RTS/CTS.
The Ctrl-S surprise
Because XOFF is Ctrl-S and XON is Ctrl-Q, a classic gotcha shows up on console ports and terminals. Press Ctrl-S by accident and the screen freezes — you just sent XOFF and paused the output. It looks exactly like a hung session. Press Ctrl-Q to send XON and it comes back to life. Worth knowing before you power-cycle something that was never actually stuck.
Configuring it
Both ends have to be set the same way. In terminal software the flow-control choice is usually None, XON/XOFF (software), or RTS/CTS (hardware). Mismatch it — one side on XON/XOFF, the other on none or hardware — and you get dropped characters under load, or a link that stalls and never recovers.
A few practical notes:
XON/XOFF works on standard ASCII framing. Any normal 7- or 8-bit setup (8-N-1 is fine) carries the codes; just make sure data bits and parity match on both ends so 0x11 and 0x13 come through clean.
Don’t turn on software and hardware flow control at the same time unless a device specifically asks for it. Pick one.
If you’re moving binary data, turn XON/XOFF off before you start.
Troubleshooting
- Link stalls and never resumes. An XOFF went out but the XON never arrived or never got recognized — a lost byte, mismatched settings, or a sender that ignores flow control. Reset the link and confirm both ends use the same flow-control mode.
- Characters dropped under load. The receiver isn’t sending XOFF early enough, or the far end ignores it. Add buffer headroom or move to hardware flow control.
- Binary file arrives corrupted. The payload contained 0x11 or 0x13 and it got eaten as flow control. Disable XON/XOFF for the transfer.
- Terminal frozen for no reason. Stray Ctrl-S. Press Ctrl-Q.
- Works one direction, not the other. Flow control is per-direction. One side may have it enabled and the other not.
Quick reference
The characters
| XON | XOFF | |
|---|---|---|
| ASCII | DC1 | DC3 |
| Hex | 0x11 | 0x13 |
| Decimal | 17 | 19 |
| Ctrl key | Ctrl-Q | Ctrl-S |
| Action | Resume | Pause |
Pick a flow control
| Situation | Use |
|---|---|
| Text or terminal, few wires | XON/XOFF |
| Binary data | RTS/CTS, or none plus protocol framing |
| High throughput | RTS/CTS |
| Over a modem or radio path | XON/XOFF |
The lines it rides on (RS-232 / V.24)
| Wire | V.24 circuit | Role |
|---|---|---|
| TXD | 103 | Carries the XOFF/XON you send |
| RXD | 104 | Carries the XOFF/XON you receive |
| GND | 102 | Signal ground |
FAQ
What do XON and XOFF stand for?
XON means “transmit on” and XOFF means “transmit off.” XON tells the sender to resume transmitting; XOFF tells it to stop. They’re the two signals behind serial software flow control.
What are the XON and XOFF codes?
XON is the ASCII DC1 character: hex 0x11, decimal 17, keyboard Ctrl-Q. XOFF is DC3: hex 0x13, decimal 19, Ctrl-S. Both come from the ASCII device-control group, not from the RS-232 standard itself.
Is XON/XOFF software or hardware flow control?
Software. The pause and resume signals are sent as characters inside the data stream, so no dedicated wires are needed. Hardware flow control (RTS/CTS) uses separate physical lines instead.
How many wires does XON/XOFF need?
Three: transmit, receive, and ground. Because the control characters travel on the data lines, a bare three-wire cable is enough — the same cable you’d use for a three-wire null modem.
Why does Ctrl-S freeze my terminal?
Ctrl-S is XOFF. Pressing it tells the terminal to pause output, which looks like a hung session. Press Ctrl-Q, which is XON, to resume. Nothing is actually broken.
Can I use XON/XOFF for binary file transfers?
Not safely. Binary data will eventually contain the bytes 0x11 or 0x13, and the receiver reads them as flow control instead of data, corrupting the transfer. Use hardware flow control or a protocol with its own framing for binary.
XON/XOFF or RTS/CTS — which should I use?
Use XON/XOFF for text over long or wire-limited paths, including modems and radios. Use RTS/CTS for binary data or high throughput, where you can run the extra wires and need every byte value to pass. Both ends must be set the same way.
