2010-05-24 1 views
1

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

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

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

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

код ниже:

+0

Код здесь: http://95.131.67.163/code.txt – Rob

ответ

1

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

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

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

+0

e.Buffer [e.Offset] = 255 - это чисто диктовать, работает ли клиент с клиентом unicode или нет, нас интересует только 255 как самое первое сообщение, которое отправляет клиент, тогда мы устанавливаем isUnicode в свой объект состояния и используем его с этого момента. Отделитель - это первое, что мы проверяем (char3) после добавления содержимого в состояние sb string. Это немного странно, так как в 80% случаев он работает без проблем, но когда мы выходим из наших ошибок, мы обнаруживаем, что char3 был найден, но строка не завершена с самого начала. Это та часть, которая не имеет смысла. – Rob

+0

Infact, кажется, что к большинству сообщений добавляется множество вопросительных знаков. Звучит как unicode-ошибка, но не уверен, где это происходит либо – Rob

+0

Например: ?????????????????????????????????? 3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e это перепутались сообщение, должно быть просто: 3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e – Rob

0

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

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