GNU readline gives the option to provide custom stdio streams.
rl_{in,out}stream. You can use fdopen to get a stdio stream from a fd (socket for example). This can be problematic if not done correctly (buffering & stuff). Official documentation has more info on all this.
You can also fork+dup2+pipe/pty and use stdin/out on the forked process.