SocketAsyncEventArgs и буферизация, когда сообщения разбиты на части - PullRequest
1 голос
/ 24 мая 2010

Сервер сокетов C #, который имеет примерно 200 - 500 активных соединений, каждое из которых постоянно отправляет сообщения на наш сервер.

Примерно в 70% случаев сообщения обрабатываются нормально (в правильном порядке и т. Д.), Однако в остальных 30% случаев мы перемешиваем сообщения, и все облажается.Следует отметить, что некоторые клиенты отправляют данные в Unicode, а другие в ASCII, так что это также обрабатывается.

Сообщения, отправляемые на сервер, представляют собой строку переменной длины, оканчивающуюся на char3, это символ char3, который мы разбиваем, кроме того, что мы продолжаем получать данные.

Может ли кто-нибудь пролить свет на наш код ProcessReceive и посмотреть, что может вызвать у нас проблемы и как мы можем решить эту небольшую проблему (здесь мы надеемся, что это небольшая проблема!)

Код ниже:

Ответы [ 2 ]

1 голос
/ 24 мая 2010

Во-первых, я уверен, что вы знаете, но это всегда стоит повторить; TCP - это поток байтов. Он ничего не знает ни о каких «сообщениях» прикладного уровня, которые, как вы можете определить, существуют в этом потоке байтов. Все успешные вызовы сокетов Recv, будь то синхронные или асинхронные, могут возвращать любое количество байтов от 1 до размера предоставленного буфера.

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

Прямо сейчас вы этого не делаете, и ваше использование e.Buffer[e.Offset] == 255 завершится неудачей, если вы получите сообщение, которое приходит по частям, как вы могли бы ссылаться на любой байт в сообщении, если сообщение разбито на несколько чтений.

0 голосов
/ 05 июня 2010

Проблема, которую я вижу, заключается в том, что вы вызываете Encoding.Unicode.GetString () для буфера, который вы получили в текущем чтении из сокета. Однако содержимое этого буфера может не являться допустимой кодировкой строки в Юникоде.

Что вам нужно сделать, это буферизовать весь поток, а затем декодировать его как строку за одну последнюю операцию после получения всех данных.

...