Для отправки данных по TCP-соединению для моего приложения я использую простой фрагмент кода:
public void Send(byte[] message)
{
if (socket != null)
{
if (stream != null)
{
stream.Write(message, 0, message.Length);
if (receiveThread == null)
{
StartReceiver();
}
}
}
}
Сокет является экземпляром класса TcpClient
, а поток - связаннымэкземпляр потока.StartReceiver()
запускает поток, который, как предполагает метод, получает данные, отправленные приложению.
Для получения данных я использую:
private void ReceiveLoop()
{
DataReceivedStruct drs;
try
{
for (; ; )
{
if (stream != null)
{
drs = new DataReceivedStruct();
drs.stream = stream;
drs.waitHandle = are;
stream.BeginRead(readBuffer, 0, readBuffer.Length, DataReceived, drs);
Console.WriteLine("Waiting to be allowed to continue");
are.WaitOne();
Console.WriteLine("Allowed, continuing loop");
}
else
{
Thread.Sleep(5);
}
}
}
catch (SocketException e)
{
DispatchRaiseException(e);
}
catch (Exception e)
{
DispatchRaiseException(e);
}
}
Опять же, используемый поток - это вышепотоковый экземпляр объекта класса TcpClient
.Объект readBuffer является byte[1024]
.Обратный вызов BeginRead
выглядит следующим образом:
private void DataReceived(IAsyncResult result)
{
DataReceivedStruct drs = (DataReceivedStruct)result.AsyncState;
NetworkStream used = drs.stream;
AutoResetEvent handle = drs.waitHandle;
used.EndRead(result);
DispatchRaiseReceived(readBuffer);
Console.WriteLine("Signalling allowance of continue for loop");
handle.Set();
}
Завершает действие чтения в потоке и передает набор данных в readBuffer.
Это работает в принципе.Я могу отправлять и получать данные из и в приложение.Существует только одна проблема с получающей стороной заявки.Когда в приложение отправляется сообщение, вызывается функция BeginRead
, после чего обратный вызов запускает и завершает операцию чтения с помощью EndRead
и передает данные для дальнейшей обработки.Это работает для одного сообщения за раз.Но становится интереснее, когда другое сообщение отправляется сразу после того, как первое сообщение вызвало BeginRead
.Затем происходит то, что EndRead
для первого сообщения еще не произошло, поэтому данные первого сообщения записываются вторым сообщением, что приводит к неверным данным.
Если я перестану использовать BeginRead
/ EndRead
и просто использовать блокирующую операцию Read
для получения данных?Или можно заблокировать поток с помощью BeginRead
/ EndRead
, чтобы второе сообщение не было получено, пока не обработано первое сообщение?