Вроде бы нашел, в чем проблема.
Если в крадце, то FD_READ появляется только, если предыдущий recv() вызвал ошибку WSAEWOULDBLOCK и если после последнего recv() в буфере есть еще данные.
И еще в каждом OnReceive() должен быть только один вызов Receive(), иначе FD_READ перестанут появляться.