I posit that the original use of control characters was strictly for non-textual usage. In other words, things that don't print. In ye olden times, that was the primary way to communicate anything other than actual text to:
- Terminals - initially printing, e.g., ASR-33, and later video terminals, e.g., ADM-3A, VT-100, etc.
- Modems - to control the modems, not just to pass text through to terminals & printers
- Any device with no capability for out-of-band control
The last is the key. In-band = control using the same transmission of data (typically, but not always, 8-bit bytes) used for the content. Out-of-band = control using some separate mechanism.
A typical example of out-of-band control is disk drives. An ST-506 drive had 3 cables: power, data, control. The drive would know when to read vs. write vs. move not based on the data cable but based on the control cable. Well, a little more complicated than that, but the point is that it wasn't arbitrary characters in the data stream that determined when to perform different actions.
In-band control is a must when you only have one transmission path, unless your data is encapsulated inside something else, a packet. In the olden days, terminals, printers and similar devices were often a 3-wire system - send, receive, ground. Sometimes they would include hardware handshaking, but that was typically limited to start/stop and possibly answer/hang up (e.g., CD on a modem) or equivalent. Additional control, such as when to move the platen (CR, LF, VT), ring a bell (BEL), or sometimes more complex operations, were sent as Control Codes. Any other method might work locally, but would not work with a remote terminal or printer, transmitted over a modem, etc.
So what has survived?
The obvious ones are CR, LF and TAB. BEL is also still supported in many devices. But there is one more that is still very often used: ESC. While the average user never sees it, a typical non-GDI (don't get me started about GDI printers...) printer relies heavily on Escape Codes - traditionally ESC followed by a manufacturer-specific sequence of text. PCL is still huge, in almost every non-GDI laser or inkjet printer, but there are other variations still commonly used in receipt printers, label printers and other devices.
ANSI escape codes are supported by many common terminal programs & operating system shells, even though the transmission process now is almost always either a directly attached device (memory mapped screen/video card) or a TCP/IP network connection.
On the other hand, codes related to flow control and some other actions are now handled out-of-band. Typically this is by encapsulating the textual data inside a packet, with transmission issues handled outside the packets (e.g., TCP/IP transmission) or other "control" information handled in a defined structured manner inside the packet. While out-of-band transmission of control information does complicate the process a bit, requiring either a second transmission path or packets of some sort, it allows for transmission of any data string, which was a real issue in the early days. For example, if you wanted to control a Hayes-compatible modem while connected, you would pause for a short time, send +++, then pause again, and the modem would switch from transmit/receive modem to control mode. Great if you wanted to do that. But a potential path for problems if you didn't want to do that. Murphy's Law says that any arbitrary string of characters + timing will occur when you least expect it.