secondthe two methods are very linearit looks like code is being executed one line after another of coursein asynciothis is an illusionbut we don' have to worry about shared memory or concurrency primitives streams the previous example should look familiar by now as it has similar boilerplate to other asyncio programs howeverthere are few differences you'll notice we called start_server instead of create_server this method hooks into asyncio' streams instead of using the underlying transport/protocol code instead of passing in protocol classwe can pass in normal coroutinewhich receives reader and writer parameters these both represent streams of bytes that can be read from and written like files or sockets secondbecause this is tcp server instead of udpthere is some socket cleanup required when the program finishes this cleanup is blocking callso we have to run the wait_closed coroutine on the event loop streams are fairly simple to understand reading is potentially blocking call so we have to call it with yield from writing doesn' blockit just puts the data on queuewhich asyncio sends out in the background our code inside the sort_request method makes two read requests firstit reads bytes from the wire and converts them to an integer using big endian notation this integer represents the number of bytes of data the client intends to send so in the next callto readexactlyit reads that many bytes the difference between read and readexactly is that the former will read up to the requested number of byteswhile the latter will buffer reads until it receives all of themor until the connection closes executors now let' look at the executor code we import the exact same processpoolexecutor that we used in the previous section notice that we don' need special asyncio version of it the event loop has handy run_in_executor coroutine that we can use to run futures on by defaultthe loop runs code in threadpoolexecutorbut we can pass in different executor if we wish oras we did in this examplewe can set different default when we set up the event loop by calling loop set_default_ executor(as you probably recall from the previous sectionthere is not lot of boilerplate for using futures with an executor howeverwhen we use them with asynciothere is none at allthe coroutine automatically wraps the function call in future and submits it to the executor our code blocks until the future completeswhile the event loop continues processing other connectionstasksor futures when the future is donethe coroutine wakes up and continues on to write the data back to the client