The problem is that you move details from a lower layer to the application level which make the design brittle and confusing. socket::read is designed to read a given number of bytes with timeout. I see no problem with this interface.
What is the actual problem? poll times out though there are a couple of byes to read?