I think that using threads with blocking sockets instead of asynchronous API is much better. In most cases, communication is sequential in its nature and the flow of operations is logically independent from other threads. Therefore, using a separate thread for each communication channel (in case of TCP) is way more straightforward, logically.
Of course, you pay for it by using thread synchronization. But you learn thread synchronization once and then use this knowledge for a lifetime, while asynchronous APIs are application-specific.
For some ideas, please see my past answers:
Multple clients from same port Number[
^],
an amateur question in socket programming[
^].
—SA