Байт поиска []

Поиск строки внутри строки очень хорошо поддерживается в .NET, но что делать, если данные, которые нужно искать, не являются строкой?

У меня есть двоичные данные, поступающие регулярными порциями через NetworkStream. Пакеты являются двоичными, но все они начинаются с последовательности байтов подписи. Я накапливаю куски в больший буфер и ищу сигнатуру начала пакета.

Я действительно ищу byte[], эквивалент метода String.IndexOf(ss). У меня неприятное предчувствие, что мне придется самому реализовать это с помощью цикла и конечного автомата.

Какие-либо предложения? К тебе!


Как и предполагалось, Array.IndexOf (byte), по крайней мере, избавит меня от явного цикла. С момента публикации мне пришло в голову найти первый байт подписи, затем попытаться найти совпадение, где должен быть последний байт подписи, а затем, если они оба совпадают, попробуйте сравнение грубой силы для остальной части строки. Этот подход имеет то преимущество, что дешево отклоняет ложные совпадения и позволяет мне дешево отклонять, когда у меня есть частичная подпись, ожидающая другого фрагмента.

Google показывает, что вышеприведенный блестящий план является вырожденным случаем алгоритма KMP или Кнута-Морриса-Пратта. С другой стороны, если Кнут написал на нем свое имя, это, вероятно, смазанная молния, с другой стороны, почему всякий раз, когда у меня появляется хорошая идея, Дональд Кнут думал об этом 25 лет назад?

Поскольку я не могу присудить очки Дональду Кнуту, думаю, они достаются Нельсону.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
405
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать Array.IndexOf, чтобы найти один байт.

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

Если вы используете TCP, вполне допустимо отключать клиента, если он лжет о размере пакета или запрашивает тупой объем памяти :)

Я не могу писать протокол, я говорю о устаревшем оборудовании. Я должен написать следующую версию, и я уже уточнил ваше предложение.

Peter Wone 10.10.2008 11:09

Можете ли вы использовать неуправляемый / небезопасный код? Если это так, я бы, вероятно, предложил изучить использование арифметики указателей для поиска в массиве байтов. Вот как действуют струны. Вы можете сделать то же самое.

другим решением может быть использование словаря для хранения ваших пакетных данных. Пусть ключ будет вашей подписью. Тогда его довольно быстро и легко найти. Несколько способов использовать байт в качестве ключа, например base64string, оболочку simepl (используйте KeyedCollection, если вы это сделаете) и т. д.

Фактически неуправляемый код - это PITA, поскольку у нас смешанная среда 32/64. Удивительно, насколько это меньше хлопот для чистого управляемого кода. Уловка-22: мне нужна подпись для разбора потока на пакеты.

Peter Wone 10.10.2008 11:05

Самыми быстрыми алгоритмами для поиска шаблонов в байтовых массивах и строках, которые я использовал, являются Бойер-Мур и простой алгоритм Бойера-Мура (полезен, когда шаблон значительно отличается от искомого текста). Я использовал это для реализации быстрого парсера mime на Java. код может быть легко перенесен в .Net (лицензия LGPL).

Другие вопросы по теме