Tcp достаточно просто пишется в синхронной модели, он прост как полено (я реализовывал частично). Асинхронность для его реализации не нужна. И по-моему, как раз она -- микроскоп для забивания гвоздей.
Асинхронность тут нужна, что бы обслуживать большое количество tcp соединений. Но при этих соединениях тебе нужно безопасно обрабатывать события типа таймаутов. Напомню, что 1 сокет - это 1 файловый дескриптор. Их на современных серверах рекомендуют делать много, но их количество всё равно конечно. И при реализации работы с tcp асинхронно тебе надо в правильной последовательности забирать и отдавать сокеты в систему.
К слову, например, если при работе RabbitMQ исчерпать количество дескрипторов в системе, то кролик распухает и в конечном результате происходит OOM. Казалось бы, какая связь между файловыми дескрипторами и памятью. :)