Besides tokio, there’s the lower level
mio crate (that tokio is based on).
Barring those, you can use a thread-per-connection model where you have blocking IO but it would block a dedicated thread (note this might not scale to lots of clients). If the remote disconnects, the blocked read/write calls would return. For example, a read would return a Ok result with 0 bytes read if the remote shuts down gracefully or it would return an Err if it’s not graceful (eg a reset). You can still get hung calls if the network disappears from you (ie packets lost) and then you can play around with tcp keepalive probes or put in an application level heartbeat/liveness protocol. But that’s now tangential to your question .