Well, if I transmit 9 characters (or less, whatever), e.g. "012345678", these
characters are displayed, followed by a '\0'.

Transmitting only 6 characters displays these 6 characters, e.g. "012345"
and 4 appended '\0' characters. That's not what I want, I want the program
to block and wait for the 10th character in the first example or the 7th,
8th, 9th and 10th character in the second example.
 
Ok, I see...
I don't really understand why you wish to async_read() char-by-char and to re-run io_service each time, instead of reading N chars at once into a buffer, but if you prefer to do so, you have to call io_service::reset() before any subsequent call to run():
//...
io.reset();

io.run();

//....