У меня есть клиент-серверное приложение, которое я недавно изменил, чтобы BeginRecieve вызывался в другой раз на том же сокете до завершения первого.Теперь первое сообщение получено отлично, но на следующем буфере для заголовка (см. Код ниже) заполнены большие жирные нули вместо данных, которые я должен получать.
public class Client
{
Socket sock;
Message message;
MessageHeader header;
byte[] headerBuffer = new byte[MessageHeader.HEADER_SIZE];
byte[] dataBuffer;
bool activeReceiver = false;
public delegate void DisconnectedHandler(Client c);
public event DisconnectedHandler Disconnected;
public delegate void DataReceivedHandler(Client c, Message m);
public event DataReceivedHandler DataReceived;
public Client(Socket sock)
{
this.sock = sock;
sock.BeginReceive(headerBuffer, 0, MessageHeader.HEADER_SIZE, SocketFlags.None, ReceiveCallback, null);
}
internal void Activate()
{
activeReceiver = true;
sock.BeginReceive(headerBuffer, 0, MessageHeader.HEADER_SIZE, SocketFlags.None, ReceiveCallback, null);
}
internal void ForceReceive()
{
if (!activeReceiver)
{
sock.BeginReceive(headerBuffer, 0, MessageHeader.HEADER_SIZE, SocketFlags.None, ReceiveCallback, null);
}
}
private void ReceiveCallback(IAsyncResult result)
{
int received;
try
{
received = sock.EndReceive(result);
if (received != MessageHeader.HEADER_SIZE && Disconnected != null)
{
Disconnected(this);
return;
}
else if (received == MessageHeader.HEADER_SIZE)
{
header = new MessageHeader(headerBuffer);
if (header.size > 0)
{
dataBuffer = new byte[header.size];
sock.Receive(dataBuffer);
message = new Message(header, dataBuffer);
if (DataReceived != null)
{
DataReceived(this, message);
}
}
message = null;
headerBuffer = new byte[MessageHeader.HEADER_SIZE];
dataBuffer = null;
if (sock != null && activeReceiver)
{
sock.BeginReceive(headerBuffer, 0, MessageHeader.HEADER_SIZE, SocketFlags.None, ReceiveCallback, null);
}
}
}
catch (SocketException sex)
{
switch (sex.SocketErrorCode)
{
case SocketError.ConnectionAborted:
case SocketError.ConnectionReset:
if (Disconnected != null)
{
Disconnected(this);
}
break;
}
}
}
А MessageHeader - это простой маленький класс:
public class MessageHeader
{
public static int HEADER_SIZE = 12;
public int type, size, source;
public MessageHeader(int type, int size, int source)
{
this.type = type;
this.size = size;
this.source = source;
}
public MessageHeader(byte[] raw)
{
if (raw.Length != HEADER_SIZE)
{
type = -1;
size = -1;
source = -1;
}
type = BitConverter.ToInt32(raw, 0);
size = BitConverter.ToInt32(raw, 4);
source = BitConverter.ToInt32(raw, 8);
}
public byte[] toBytes()
{
byte[] bytes = new byte[HEADER_SIZE];
BitConverter.GetBytes(type).CopyTo(bytes, 0);
BitConverter.GetBytes(size).CopyTo(bytes, 4);
BitConverter.GetBytes(source).CopyTo(bytes, 8);
return bytes;
}
}
То, как это работало (и работало безупречно), было activeReceiver, не было чем-то, BeginReceive вызывалось бы в конце каждого обратного вызова.Теперь новая модификация - переменная activeReceiver вместе с методами ForceReceive и Activate.До тех пор, пока не будет безопасно перевести клиента обратно в режим автоматического вызова BeginReceive, ForceReceive () вызывается для него извне после обработки данных делегатом DataReceived.Когда становится безопасным повторно вводить исходное поведение, вместо ForceReceive вызывается Activate, и с этого момента он возвращается к исходному поведению.В моем единственном возможном тестовом примере этот этап никогда не достигается.Существует 1 обмен сообщениями между сервером и клиентом, который проходит нормально, затем клиент блокируется, когда сервер не отвечает на следующее сообщение.
Обратите внимание, что когда я получаю 0-е (чтоэто второе сообщение от клиента в целом) мы вводим случай, когда в headerBuffer получено правильное количество байтов, только все 12 из них являются 0-овами.
ОБНОВЛЕНИЕ: Так что я обошел это сдействительно сложное решение, которое расточительно с точки зрения памяти, но хотело бы сделать более изящное и более эффективное решение для памяти, так что если кто-нибудь это поймет, я все равно буду рад увидеть разгадку этой тайны.