Create Your Own Event Queue 90 In the loop, we retrieve the token that identifies which Tcp Stream we received an event for. As we explained earlier in this example, this token is the same as the index for that particular stream in the streams collection, so we can simply use it to index into our streams collection and retrieve the right Tcp Stream. Before we start reading data, we create a buffer with a size of 4,096 bytes (you can, of course, allocate a larger or smaller buffer for this if you want to). We create a loop since we might need to call read multiple times to be sure that we've actually drained the buffer. Remember how important it is to fully drain the buffer when using epoll in edge-triggered mode. We match on the result of calling Tcp Stream::read since we want to take different actions based on the result: If we get Ok(n) and the value is 0, we've drained the buffer; we consider the event as handled and break out of the loop. If we get Ok(n) with a value larger than 0, we read the data to a String and print it out with some formatting. We do not break out of the loop yet since we have to call read until 0 is returned (or an error) to be sure that we've drained the buffers fully. If we get Err and the error is of the io::Error Kind::Would Block type, we simply break out of the loop. We don't consider the event handled yet since Would Block indicates that the data transfer is not complete, but there is no data ready right now. If we get any other error, we simply return that error and consider it a failure. Note There is one more error condition you' d normally want to cover, and that is io::Error Kind::Interrupted. Reading from a stream could be interrupted by a signal from the operating system. This should be expected and probably not considered a failure. The way to handle this is the same as what we do when we get an error of the Would Block type. If the read operation is successful, we return the number of events handled. Be careful with using Tcp Stream::read_to_end Y ou should be careful with using Tcp Stream::read_to_end or any other function that fully drains the buffer for you when using non-blocking buffers. If you get an error of the io::Would Block type, it will report that as an error even though you had several successful reads before you got that error. Y ou have no way of knowing how much data you read successfully other than observing any changes to the &mut Vec you passed in.