You have two threads that are wanting to read at the same time, and write at the same time. This is not a good design choice. It is a race between the threads, you don't know which thread will actually receive which message, so BOTH threads have to be ready to reply to KeepAlives, and BOTH threads have to be ready to handle non-KeepAlive replies. And worse, it is possible that one thread may read bytes that the other thread is expecting. It is just not a good situation to be in.
I would suggest a completely different approach. Have 2 worker threads - 1 thread whose sole task is to read ALL incoming packets, and 1 thread whose sole task is to write ALL outgoing packets. When the reading thread receives a message, if the message is a KeepAlive then the reading thread can ask the writing thread to send a reply, otherwise the reading thread can dispatch the message for processing as needed (which probably shouldn't be done in the main thread, if you can avoid it). When the main thread (or any other thread) wants to send a message, it can ask the writing thread to send it.
This way, you don't need to synchronize the reads and writes anymore. Only synchronize the requests for sending messages.
Reading thread:
Reader.Execute
while not Terminated
receive data (no timeout)
if message type is keepalive
create ack message
Writer.Send(message)
else
dispatch message for processing
Writing thread:
Writer.Send(message)
queue.lock
try
queue.add(message)
signal.set
finally
queue.unlock
end
Writer.Execute
while not Terminated
if signal.wait(timeout)
try
queue.lock
try
make copy of queue
queue.clear
signal.reset
finally
queue.unlock
end;
send messages in copy
finally
copy.clear
end;
Main thread:
Main.DoSomething
create xml message
Writer.Send(message)
Main.DataReceived(data)
parse data
if should send next message
create xml message
Writer.Send(message)