2012-05-17 4 views
0

У меня был код (давайте предположим, что приложение простого чата), я использовал Tcp с синхронизацией. но поскольку способ Async лучше вообще, хотя его сложнее настроить, я решил изменить путь от синхронизации до асинхронного. но теперь я столкнулся с некоторыми проблемами, используя async.Проблема с получением сообщений с использованием Tcp с Async

  1. Размер буфера: Я знаю, что нам нужно учитывать ограниченный размер байтов, чтобы получить байты от однорангового узла. Я прочитал много статей, но моя проблема не решена, у меня очень простой, но бесполезный подход, чтобы справиться с этим, поставив персонажа в конце каждого сообщения; то приемник может понять, когда сообщение полностью получено. но у меня есть еще одна проблема, которая мешает мне выполнить этот подход дальше к другим проблемам, которые у меня есть для меня.

Позвольте мне объяснить мою проблему следующим кодом:

public void Send(byte[] message, Socket connection) 
{ 
    connection.BeginSend(message, 
         0, 
         message.Length, 
         SocketFlags.None, 
         new AsyncCallback(OnSend), 
         connection); 
} 

и по методу OnSend, я просто использую connection.EndSend (результат), где результат является IAsyncResult. но когда я затем вызываю метод отправки дважды, как следующий код, обратный вызов OnReceive получит оба из них как одно единственное сообщение.

Send(Encoding.Unicode.GetBytes("Hello")); 
Send(Encoding.Unicode.GetBytes("Bye")); 

мой OnReceiveMethod будет использовать Console.WriteLine (сообщение); где message - строка, полученная от однорангового узла. и выход с помощью синхронизации путь должен быть

Здравствуйте

Bye

но в асинхронном образом я получаю это как одно сообщение не два, так что печатается

HelloBye

С уважением, Peyman Mortazavi

ответ

2

При синхронном вызове вы гарантируете, что первое сообщение полностью отправлено перед отправкой второго. Однако при использовании асинхронных методов вы просто добавляете два сообщения в исходящую очередь, ожидая отправки. Если вам удастся нажать его в нужное время, он может отправить их как два отдельных сообщения, но так как вы добавите их так быстро, это, скорее всего, отправит их вместе. Если вы считаете, что связь со стандартом TCP/IP является единственным непрерывным потоком данных, вам будет намного лучше. Вам нужно отформатировать ваши сообщения таким образом, чтобы вы могли определить, где они начинаются и заканчиваются. Когда вы получаете данные через сокет, вы должны продолжать добавлять полученные сообщения в буфер до тех пор, пока вы не определите (на основе форматирования данных), что вы получили полное сообщение. Вы не должны полагаться на каждое чтение из сокета, чтобы быть единственным полным сообщением. Вы должны ожидать, что это может быть только частичное сообщение или даже несколько сообщений.

+0

Право, теперь я жду 10 миллисекунд при методе отправки, который очень короткий, но решает проблему. и в пользовательском формате я могу понять, когда сообщение запущено и закончилось. – Peyman

4

Должен сказать, что я действительно не согласен с просто переключением на синхронные сокеты для преодоления этой проблемы. Гораздо лучший подход мог бы использовать Queue<string> (например), куда вы отправляете сообщения при отправке вызова.

После этого у вас есть асинхронные пакеты деактивации сокета из этой очереди и отправьте следующий, когда текущая выполняется, до тех пор, пока очередь не будет пуста.

Тогда вы можете отказаться от вызова BeginSend еще до появления сообщений в очереди.

Смежные вопросы