implement a transport with 2 independent sockets for sending and receiving

implementing a tie-breaking logic is error-prone due to netty's asynchronous nature. i think the code would be much simpler if we use two sockets for each peer, one for sending and the other for receiving.