Winsock. Парсинг входящих пакетов.

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Winsock. Парсинг входящих пакетов.

Сообщение Izgoy » 18.06.2006 (Вс) 20:13

Доброго время суток!

Описываю суть проблеммы. Что имеется - входящие пакеты. Имеют структуру команда1+параметры_команды1+команда2+параметры_команды2 итд. Как лучше всего резать пакет с тем, чтобы разделить эти команды?

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 18.06.2006 (Вс) 20:15

Разделители - "+" и "_"?

Парсить сначала Split'ом по "_", затем каждый из блоков "команда+ее параметры" еще раз Split'ом по "+".

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 20:31

нет.. разделители только "#" при этом команды с предыдущими параметрами не разделяются вообще никак, идут даже без пробелов.
пример:
login_result#okklans_info#7#101#1148401685#klan1#102#0#klan2#103#0#klan3#104#0#klan4# 105#0#klan5#106#0#klan6#107#0#klan7startinfo#char#24#2220#1084#14#10#8#8#176#7697#0#21#0#0#54# 0#3#0#0#346#373#8#11#9240#9203#9244#7952#557#6763#4840#556#9215#559#3269#8645#4588#4587#2129#2129#2129#2456#2460#2129# 2129#2129#2458#2460#2129#2129#2129#2458#2456#2949#2129#2949#2456#7899#2457#2129#0#731829#0#0#24#2#2#6#0#1#0#0#0# 0#0#0#7062#0#1998#4#2#1#3#5#3#1#17#1#0#2#0#0lf#141#9328#perss1#64#0#0#0#0#0#8605#perss2#201#10#1#0#102#1# 13300#perss3#74#0#0#0#0#0#15851#perss4#67#0#0#0#0#0#12262#perss5#143#0#0#0#0#0#

Жирным выделил сами команды.
Тоесть мне кажется нужно отлавливать в строке команды.. Я вот думаю делать это instr и вырезать mid-ом.. Но выглядит это слишком запутанно. Может есть что-то проще?

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 20:36

Что надо получить? отдельные строки:
login_result#ok

klans_info#7#101#1148401685#klan1#102#0#klan2#103#0#klan3#104#0#klan4# 105#0#klan5#106#0#klan6#107#0#klan7

startinfo#char#24#2220#1084#14#10#8#8#176#7697#0#21#0#0#54# 0#3#0#0#346#373#8#11#9240#9203#9244#7952#557#6763#4840#556#9215#559#3269#8645#4588#4587#2129#2129#2129#2456#2460#2129# 2129#2129#2458#2460#2129#2129#2129#2458#2456#2949#2129#2949#2456#7899#2457#2129#0#731829#0#0#24#2#2#6#0#1#0#0#0# 0#0#0#7062#0#1998#4#2#1#3#5#3#1#17#1#0#2#0#0

lf#141#9328#perss1#64#0#0#0#0#0#8605#perss2#201#10#1#0#102#1# 13300#perss3#74#0#0#0#0#0#15851#perss4#67#0#0#0#0#0#12262#perss5#143#0#0#0#0#0#

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.06.2006 (Вс) 20:41

Как предлагаешь отличать команду от параметров?
Вот klan1 -- это параметр или команда?
Изображение

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 20:43

Я выделил команды жирным. Тоесть все команды мне известны и, допустим, находятся в одном массиве.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 18.06.2006 (Вс) 20:51

Написать сплит вручную который в качестве сплиттера может понимать массив (как в php) и разделить строк на массив, где первый (нулевой) элемент - команда, а последующие - параметры.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 20:56

тоесть новую функцию? можна подробнее?

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.06.2006 (Вс) 20:58

Izgoy писал(а):Я выделил команды жирным. Тоесть все команды мне известны и, допустим, находятся в одном массиве.

Если присутствие сторонней дллки не вызывает проблем, то самым кошерным было бы написать отдельный лексер на flex. (Опыт есть, могу что-нибудь подсказать.)

Сплит по массиву разделителей -- весьма неэффективно (что там будет внутри? двойной цикл из обычных сплитов? или престидижитация с Mid-ами?)
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 18.06.2006 (Вс) 21:00

Ну... т.е. есть массив Array("Kam", "Lam", "Bam")

и строку "milimiratKamsinkiramaLambugalcaBamcista" пропустив через такую функцию -> ты получишь массив

milimirat
sinkirama
bugalca
cista
________________
Добавлено позже: А где уведомление об ответе tyomitch'а?
А вообще я бы посоветовал так.

<Через минуту тут будет код>
Последний раз редактировалось Хакер 18.06.2006 (Вс) 21:02, всего редактировалось 1 раз.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 21:02

tyomitch писал(а):Если присутствие сторонней дллки не вызывает проблем, то самым кошерным было бы написать отдельный лексер на flex. (Опыт есть, могу что-нибудь подсказать.)
Э.. Я в этом ни бум-бум.. Если не затруднит - дай что-то почитать по этому поводу, либо поясни немного, о чем речь.

Хакер
Такой результат и нужен. Как достичь? Если есть пример буду благодарен, если нету - поясни немного..

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.06.2006 (Вс) 21:06

Izgoy писал(а):
tyomitch писал(а):Если присутствие сторонней дллки не вызывает проблем, то самым кошерным было бы написать отдельный лексер на flex. (Опыт есть, могу что-нибудь подсказать.)
Э.. Я в этом ни бум-бум.. Если не затруднит - дай что-то почитать по этому поводу, либо поясни немного, о чем речь.

Отличный туториал есть на http://epaperpress.com/lexandyacc/thl.html -- но он не по-русски. Подходит?
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 18.06.2006 (Вс) 21:13

Щас... я придумал алгоритм... думаю он подойдёт.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.06.2006 (Вс) 21:17

Хакер, однопроходный и линейный по длине входной строки -- слабо? ;-)
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 18.06.2006 (Вс) 21:37

Вобщем вот код, вставь в любую процедуру (Например Form_Click)
и посмотри что будет
Код: Выделить всё



Dim aCommands()
Dim aCommands()

aCommands = array("login_result", "some_epa_command", "mugal", "exit", "cmd1", "cmd2", "cmd3", "cmd4")

dataline = "Cmd1#12#25#77#33#login_result#ok#pazak#cmd3#параметры комманды 3#exit#exitcode777#mugal#mu1#mu2#mu3"

'_________
'пошёл сам алгоритм

for i = LBound(aCommands) To UBound(aCommands)
dataline = Replace(dataline, aCommands(i) + "#", chr(0) + aCommands(i) + "#")
next i

aCommandLines = split(dataline, chr(0))
for i = LBound(aCommandLines) To UBound(aCommandLines)
aTempArr = split(aCommandLines(i), "#")
    output$ = output$ + "Команда: " + aTempArr(0) + vbNewLine
    for j = 1 To UBound(aTempArr)
        if aTempArr(j) <> "" then
            output$ = output$ + "---параметр:" + aTempArr(j) + vbNewLine
        end if
    next j
next i
MsgBox output$
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Izgoy
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 18.06.2006 (Вс) 19:52

Сообщение Izgoy » 18.06.2006 (Вс) 21:52

Хакер писал(а):Вобщем вот код, вставь в любую процедуру (Например Form_Click)
и посмотри что будет"
Красавчик =) Спасибо огромное!! =)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 18.06.2006 (Вс) 22:11

Вот более правильный код, тот я проверил с твоим примером и он рухнул и не показал параметры первой команды.

Вот новый код:
Код: Выделить всё

Dim aCommands()

aCommands = array("login_result", "klans_info", "startinfo", "lf", "cmd1", "cmd2", "cmd3", "cmd4")

dataline = "login_result#okklans_info#7#101#1148401685#klan1#102#0#klan2#103#0#klan3#104#0#klan4# 105#0#klan5#106#0#klan6#107#0#klan7startinfo#char#24#2220#1084#14#10#8#8#176#7697#0#21#0#0#54# 0#3#0#0#346#373#8#11#9240#9203#9244#7952#557#6763#4840#556#9215#559#3269#8645#4588#4587#2129#2129#2129#2456#2460#2129# 2129#2129#2458#2460#2129#2129#2129#2458#2456#2949#2129#2949#2456#7899#2457#2129#0#731829#0#0#24#2#2#6#0#1#0#0#0# 0#0#0#7062#0#1998#4#2#1#3#5#3#1#17#1#0#2#0#0lf#141#9328#perss1#64#0#0#0#0#0#8605#perss2#201#10#1#0#102#1# 13300#perss3#74#0#0#0#0#0#15851#perss4#67#0#0#0#0#0#12262#perss5#143#0#0#0#0#0#"

'_________
'пошёл сам алгоритм
dataline = "#" + dataline
for i = LBound(aCommands) To UBound(aCommands)
dataline = Replace(dataline, "#" + aCommands(i) + "#", chr(0) + aCommands(i) + "#")
next i

aCommandLines = split(dataline, chr(0))
for i = LBound(aCommandLines) + 1 To UBound(aCommandLines)
aTempArr = split(aCommandLines(i), "#")
    output$ = output$ + "Команда: " + aTempArr(0) + vbNewLine
    for j = 1 To UBound(aTempArr)
        if aTempArr(j) <> "" then
            output$ = output$ + "---параметр:" + aTempArr(j) + vbNewLine
        end if
    next j
next i
MsgBox output$

—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.06.2006 (Вс) 22:13

Хакер, на мой вопрос тоже ответь :-)
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 0:30

А какой у тебя ко мне вопрос???
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 0:43

Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 0:50

C двумя вложенными циклами пойдёт?

for
for

next
next
?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 0:56

Если по строке ты пробегаешь один раз*, то пойдёт.


* Вызовы Split и Replace каждый считаются за проход по строке. Потому что это они и есть.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 0:57

только mid будет :lol:
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 1:02

Ок, давай :-)

Чем только люди по ночам не занимаются....
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 1:10

Код: Выделить всё
Dim aCommands()

aCommands = array("cmd1", "cmd2", "cmd3", "cmd4")

dataline = "cmd1#01#02#03#04#cmd2#777#888#999#cmd4#123#456#789#101112#cmd3#kmd3_parametr1#parametr2"

'_________
'пошёл сам алгоритм
for i = 1 To Len(dataline)
    csign$ = Mid$(dataline, i, 1)
    if csign$ = "#" Or i = Len(dataline) then
        for j = LBound(aCommands) To UBound(aCommands)
            if buffer$ = aCommands(j) then IsCmd = IsCmd Or True
        next j
        output$ = output$ + IIf(IsCmd, "Команда: ", "---параметр:") + buffer$ + vbCrLf
        buffer$ = ""
        IsCmd = False
    else
        buffer$ = buffer$ + csign$
    end if
next i
Debug.print output$


Чем только люди по ночам не занимаются....

Не говори :lol: 4.09 все нормальные люди спят, а мы тут моды пишем и алгоритмы на перекурах придумываем.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 1:21

Хакер писал(а):
Код: Выделить всё
        for j = LBound(aCommands) To UBound(aCommands)
            if buffer$ = aCommands(j) then IsCmd = IsCmd Or True
        next j


Тут как будто бы нелинейность по длине входной строки: что, если в буфер$ набьётся 1000 символов? и строки в aCommands такой же длины?

Во-вторых, у Izgoy нет разделителя между последним параметром одной команды, и следующей командой.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 1:31

1) не понял, причём тут 1000 символов.

2) Упс... а вот этого я не заметил.

Тогда для нормального варианта кода, правилным будет слудующий код:

Код: Выделить всё
Dim aCommands()

aCommands = array("login_result", "klans_info", "startinfo", "lf", "cmd1", "cmd2", "cmd3", "cmd4")

dataline = "login_result#okklans_info#7#101#1148401685#klan1#102#0#klan2#103#0#klan3#104#0#klan4# 105#0#klan5#106#0#klan6#107#0#klan7startinfo#char#24#2220#1084#14#10#8#8#176#7697#0#21#0#0#54# 0#3#0#0#346#373#8#11#9240#9203#9244#7952#557#6763#4840#556#9215#559#3269#8645#4588#4587#2129#2129#2129#2456#2460#2129# 2129#2129#2458#2460#2129#2129#2129#2458#2456#2949#2129#2949#2456#7899#2457#2129#0#731829#0#0#24#2#2#6#0#1#0#0#0# 0#0#0#7062#0#1998#4#2#1#3#5#3#1#17#1#0#2#0#0lf#141#9328#perss1#64#0#0#0#0#0#8605#perss2#201#10#1#0#102#1# 13300#perss3#74#0#0#0#0#0#15851#perss4#67#0#0#0#0#0#12262#perss5#143#0#0#0#0#0#"

'_________
'пошёл сам алгоритм
dataline = "#" + dataline
for i = LBound(aCommands) To UBound(aCommands)
dataline = Replace(dataline, aCommands(i) + "#", chr(0) + aCommands(i) + "#")
next i

aCommandLines = split(dataline, chr(0))
for i = LBound(aCommandLines) + 1 To UBound(aCommandLines)
aTempArr = split(aCommandLines(i), "#")
    output$ = output$ + "Команда: " + aTempArr(0) + vbNewLine
    for j = 1 To UBound(aTempArr)
        if aTempArr(j) <> "" then
            output$ = output$ + "---параметр:" + aTempArr(j) + vbNewLine
        end if
    next j
next i
MsgBox output$


а для извращенского щас сделаю :)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 19.06.2006 (Пн) 1:44

Вот
Код: Выделить всё

Dim aCommands()

aCommands = array("cmd1", "cmd2", "cmd3", "cmd4")

dataline = "cmd1#01#02#03#04cmd2#777#888#999cmd4#123#456#789#101112cmd3#kmd3_parametr1#parametr2"

'_________
'пошёл сам алгоритм
for i = Len(dataline) To 1 Step -1
    csign$ = Mid$(dataline, i, 1)
    if csign$ = "#" then
        output$ = "---параметр:" + buffer$ + vbCrLf + output$
        buffer$ = ""
    else
        for j = 1 To UBound(aCommands)
            if buffer$ = aCommands(j) then
                output$ = "Команда:" + buffer$ + vbCrLf + output$
                buffer$ = ""
                exit for
            end if
        next j
       
        buffer$ = csign$ + buffer$
    end if
next i
Debug.print output$
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 11:23

Хакер писал(а):1) не понял, причём тут 1000 символов.

Это я, ввиду позднего часа, недостаточно корректно выразил свою мысль.

Имелось в виду: у тебя в отквоченном внутреннем цикле может выполняться (длина строки)*(число команд) операций, что для длинной строки составит существенное время.

Есть способ реализовать его со сложностью, если не вру, (длина строки)+(суммарная длина команд). Если сами команды известны заранее, то код, дающий второе слагаемое, можно выполнить на этапе компиляции, и заложить в программу его готовые результаты.

Именно это и делает flex.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.06.2006 (Пн) 18:51

полу-оффтоп: может мне написать заметку на тему "Долой самопальные парсеры из Instr, Mid и Split"?
Кто-нибудь воспримет её как руководство к действию? или все прочитают, забудут и будут продолжать для каждой задачи выдумывать новый парсер?
А то сочинять для этого демонстрационный код, если всё равно никто не станет пользоваться, -- обидно...
Изображение

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: SemrushBot, Yandex-бот и гости: 64

    TopList