Сейчас на форуме: tyns777 (+5 невидимых)

 eXeL@B —› Программирование —› Протокол передачи (Асинхронные сокеты + динамический буфер)
Посл.ответ Сообщение


Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 24 августа 2007 22:45
· Личное сообщение · #1

Вообщем облазил я все, много чего прочитал и все фигня полная))) Да вот так! ... Сейчас у меня просто есть желание сделать хороший , многопоточный , с расширяемым буфером , хорошим парсингом , и возможностью отладки ПРОТОКОЛ передачи данных на асме через ТСП ИП... Вот хочу начать сейчас ...и конечно прошу вашу критику , помощь , рецензии и посылы ))) хахаха да .... нет это не смешно я на полном серьезе, прочитал просто про дзен програмирования и буду пробовать (тож шучу) .... Честно сказть у меня нет большого опыта програмирования такого рода задач, поэтому все кого это интересует помогут. Тем более что многие говорят в сети нет хорошей информации по Асинхронным сокетам на Асме , Вы скажите проще сделать на Си , но Си я не знаю ( да да да Буду Учить но позже , извеняйте! ) , и надо на асмеа не на Си ! .... Так что такие дела Уважаемые Пупсы ..

Вообщем
вот, постепенно я буду выкладывать участки кода и то что хотелось бы там сделать
SOCKETCONN STRUCT
hSock SOCKET (0)
sockRemoteAddr sockaddr_in <>
clientName db CLIENT_NAME_SIZE dup (0)
sockID BYTE (0)
sockState BYTE (0)
nextSocketConn DWORD (0) ; LPSOCKETCONN
SOCKETCONN ENDS

; achIOBuf db RECVBUF_SIZE dup (0)

LPSOCKETCONN TYPEDEF PTR SOCKETCONN
SOCKETCONN_SIZE equ SIZEOF SOCKETCONN

SENDPACKET STRUCT
lpSockConn LPSOCKETCONN (0)
lpSendBuffer DWORD (0)
bufferSize DWORD (0)
bytesSent DWORD (0)
nextSendPacket DWORD (0) ; LPSENDPACKET
SENDPACKET ENDS

LPSENDPACKET TYPEDEF PTR SENDPACKET
SENDPACKET_SIZE equ SIZEOF SENDPACKET
;MAX_SENDPACKETS equ 32



Если сервер будет иметь много соединений ..хотя лучше ограничить их до скажем 12. Далее как я понимаю нужно как то обозначить наш пакет. Вот структура выше! ...
Как обращаться с ними я честно пока не знаю . Допустим я сформировал пакет на серваке и отправил его!!!

Но он большой!!! И пришел частями ...значит мне надо собирать все в динамически расширямый буфер, далее проверять есть ли целый пакет , если да , то Парсить его и далее ... Как сделать это лучше я пока не знаю .... Я за сегодня написал фиговенький Парсер строки ))))))))
Да вот так ))) Короче там много чего не так ... хотябы в методе парсинга ...во как ... Я выложу это все во вложенном файле ...там будет уже собранный вариант. Вот .... вообщем жду коментов и советов .........

Уважаемые Гугломаны )))))) не послыайте на х.... гуглю ))) там уже был , сидел 2 месяца ...

2255_24.08.2007_CRACKLAB.rU.tgz - parser.zip

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube





Ранг: 387.4 (мудрец)
Активность: 0.170
Статус: Участник
системщик

Создано: 25 августа 2007 01:16 · Поправил: s0larian
· Личное сообщение · #2

Чувак, ты уже подобный вопрос задавал... я тебе в общем подсказал, и предложил выкладывать исходник на С или С++. IMHO такую вещь писать на асме - себя не уважать. Потратишь больше времяни на отладку простейших структур, управление памятью и парсинг чем на сами сокеты.

По поводу модели - вот тебе пример простого сервера который принемает, скажем, что-то типа SQL запростов, построенного на одном worker thread-e:
- socket()
- bind()
- listen()

for (;;)
- select()

- для каждого нового соединения accept(), и добавляешь в список. Назад в select().
- для каждого recv() парсишь свой пакет, если есть весь пакет, то отправляешь назад результат. Назад в select().
- для каждого события PostMessage() в главный поток со строчкой лога. (client connected, rx: blah, tx: blah)

Пакетная структура (например):
select <column> from <table> ;

Парсинг: накапливаешь данные пока не увидишь метку ";". Потом разбираешь каманду на части (regex) и посылаешь ответ.

Память: у каждого соединения свой буфер в несколько кило. Этого достаточно для нескольких сотен команд. Если не влазит, то closesocket() т.к. это явно не твой протокол.

Что ещё... думаю начинаюцему "насильнику" тут довольно много писанины... Просто скачай пример и дорабарывай его. Такого на гугле немеряно



Ранг: 59.9 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 августа 2007 01:36 · Поправил: El_Diablo
· Личное сообщение · #3

Да уж парсинг на асме это жесть =
Не хватает тех же регэкспов
хотя думаю эта статья че-нить да прояснит
http://wasm.ru/article.php?article=comregexp http://wasm.ru/article.php?article=comregexp
З.Ы.я бы для начала реализовал бы какой-нить пакет,который хотябы как-то писан и инфа есть (например протокол мейл агента),а потом бы уже свой начала делать




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 25 августа 2007 22:07
· Личное сообщение · #4

=) Я теперь не спрашиваю , а тут буду все писать что да как делаю ..вот . Даа я немного того , чтоб писать на асме это , но вот так мне хочется ))) Спасибо за отклик...знаю что не легко но !!!! надо!

String Parser

.386
.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

parser proto :dword
process_word proto :dword
command1 proto
command2 proto
command3 proto
command4 proto
command5 proto

table_item struct
istring dd ? ; address of string
ilength dd ? ; length of string
ilabel dd ? ; address of procedure
table_item ends

.data
szc1 db "command1",0 ; first command
szc2 db "command2",0 ; second command
szc3 db "command3",0 ; third command
szc4 db "command4",0 ; fourth command
szc5 db "command5",0 ; fifth command

; command/proc lookup table
itable table_item < szc1, 8, command1 > ; associate the first command with the command1 procedure
table_item < szc2, 8, command2 > ; associate the second command with the command2 procedure
table_item < szc3, 8, command3 > ; associate the third command with the command3 procedure
table_item < szc4, 8, command4 > ; associate the fourth command with the command4 procedure
table_item < szc5, 8, command5 > ; associate the fifth command with the command5 procedure
table_item < 0, 0, 0 > ; blank terminator required by process_word

; other strings used in application
sztitle db "parser_test",0
c1string db "Command 1",13,10,0
c2string db "Command 2",13,10,0
c3string db "Command 3",13,10,0
c4string db "Command 4",13,10,0
c5string db "Command 5",13,10,0

prompt db "-",0
command_line db 2025 dup(0)

.data?
dwlen dd ?

.code
application proc
call [GetCommandLine]
@@: inc eax
cmp byte ptr [eax], 0Dh
je @f
cmp byte ptr [eax], 00h
je @f
cmp byte ptr [eax], 0Ah
je @f
cmp byte ptr [eax], ' '
jne @b
inc eax
lea edx, command_line
push edx
push eax
push edx
call [lstrcpy]
call [lstrlen]
cmp eax, 00h
jne @@parse_command_line

@@: lea edx, command_line
lea ebx, prompt
push 2024
push edx
push ebx
push 2025
push edx
call [RtlZeroMemory]
call [StdOut]
call [StdIn]

lea edx, command_line
@@test_q:
cmp byte ptr [edx], 'q'
je @@test_u
cmp byte ptr [edx], 'Q'
je @@test_u
jmp @@parse_it

@@test_u:
cmp byte ptr [edx+1],'u'
je @@test_i
cmp byte ptr [edx+1],'U'
je @@test_i
jmp @@parse_it

@@test_i:
cmp byte ptr [edx+2],'i'
je @@test_t
cmp byte ptr [edx+2],'I'
je @@test_t
jmp @@parse_it

@@test_t:
cmp byte ptr [edx+3],'t'
je @@finished
cmp byte ptr [edx+3],'T'
je @@finished

@@parse_it:
push edx
call [parser]
jmp @b

@@parse_command_line:
lea edx, command_line
push edx
call [parser]
cmp eax, 00h
jne @@finished
jmp @f
lperr:
BYTE "Parsing failed!",13,10,0
@@: push lperr
call [StdOut]

@@finished:
push NULL
call [ExitProcess]
xor eax, eax
ret
application endp

parser proc uses edi esi string:dword
local pcheap:DWORD
local lplast:DWORD
local szword:DWORD
local strlen:DWORD

push string
call [lstrlen]
cmp eax, 00h
jne @f
xor eax, eax
ret
@@: mov strlen, eax

call [GetProcessHeap]
cmp eax, 00h
jne @f
xor eax, eax
ret
@@: mov pcheap, eax

push strlen
push HEAP_ZERO_MEMORY
push pcheap
call [HeapAlloc]
cmp eax, 00h
jne @f
xor eax, eax
ret
@@: mov szword, eax

mov edi, szword
mov esi, string
mov ecx, strlen
mov lplast, edi

@@continue:
cmp ecx, 00h
je @@end_of_string
mov al, byte ptr [esi]
cmp al, 0Dh
je @@end_of_string
cmp al, 0Ah
je @@end_of_string
cmp al, 3Bh
je @@end_of_string
cmp al, 00h
je @@end_of_string
cmp al, 20h
je @@end_of_word
cmp al, 09h
je @@end_of_word

@@add_char:
mov byte ptr [edi], al
dec ecx
inc esi
inc edi
xor eax, eax
jmp @@continue

@@end_of_word:
mov byte ptr [edi], 00h
push lplast
call [process_word]
dec ecx
inc esi
inc edi
xor eax, eax
mov lplast, edi
jmp @@continue

@@end_of_string:
mov byte ptr [edi], 00h
push lplast
call [process_word]

push szword
push NULL
push pcheap
call [HeapFree]
cmp eax, 00h
jne @f
xor eax, eax
ret
@@: mov eax, 1
ret
parser endp

process_word proc uses esi edi szword:dword
local wrdlen:DWORD

pushad

push szword
call [lstrlen]
cmp eax, 00h
jne @f
xor eax, eax
ret
@@: mov wrdlen, eax

lea ebx, itable
assume ebx:ptr table_item

@@continue:
mov eax, [ebx].ilength
cmp eax, 00h
je @@unknown_word

cmp wrdlen, eax
jne @@do_next

mov esi, [ebx].istring
mov edi, szword
mov ecx, wrdlen

@@: mov al, byte ptr [esi]
cmp al, byte ptr [edi]
jne @@do_next
cmp ecx, 00h
je @f
inc esi
inc edi
dec ecx
jmp @b
@@: call [ebx].ilabel

assume ebx:nothing
popad

mov eax, 1
ret

@@do_next:
add ebx, 04h
jmp @@continue

@@unknown_word:

assume ebx:nothing
popad

mov eax, 1
ret
process_word endp

command1 proc
lea ebx, c1string
push ebx
call [StdOut]
ret
command1 endp

command2 proc
lea ebx, c2string
push ebx
call [StdOut]
ret
command2 endp

command3 proc
lea ebx, c3string
push ebx
call [StdOut]
ret
command3 endp

command4 proc
lea ebx, c4string
push ebx
call [StdOut]
ret
command4 endp

command5 proc
lea ebx, c5string
push ebx
call [StdOut]
ret
command5 endp

end application


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 59.9 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 августа 2007 00:24 · Поправил: El_Diablo
· Личное сообщение · #5

А тут нет тега типа [code][/code] как в других форумах,а то такой листинг ...
По теме автор пиши еще




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 26 августа 2007 18:29
· Личное сообщение · #6

Вообщем допустим я заполнил структуру !!! Отправил ее ! 2 отправил или 3 . Допустим парсером я разделил пакеты. Вот вопрос ....могу ли я обращаться к пакету как к структуре ? .... если да то как это делается ?

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube





Ранг: 387.4 (мудрец)
Активность: 0.170
Статус: Участник
системщик

Создано: 27 августа 2007 19:57 · Поправил: s0larian
· Личное сообщение · #7

mak пишет:
Вот вопрос ....могу ли я обращаться к пакету как к структуре ? .... если да то как это делается ?

можно, если у тебя всегда x86/little_endian машина Делается в С через каст:

void process(char *buffer)
{
Packet *packet = (Packet *)buffer;
}


только это не самый лучший вариант - зависит от упаковки (padding), машины (endian, x86, 64 bit). У меня в нескольких проектах был ASCII протокол - что б в лог можно было записать легко. Но, на самом деле, это не имеет значения. Протокол jabber вообще XML использует для обмена данными:

<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 28 августа 2007 19:55
· Личное сообщение · #8

короче я еще ковыряюсь ...постепенно строю вот что еще нарыл ... в приложении

описание

Маленький и удобный(если минут 10 посидеть и разобраться) сетевой движок, НЕ компонент(чтобы можно было делать приложения не используя формы и VCL). Асинхронные сокеты, простое создание пакетов и возможность создания статических пакетов(тогда пакет минимум весит 1 байт). На сервере создан список клиентов с дополнительными полями(data : Pointer и т.д.).
В самых ответственных местах коментрирована каждая строчка. Полностью на api, правда пока только TCP, но скоро поставлю чтобы было переключение между TCP и UPD, хотя мне UPD очень не нравится. Обязательно скажите что не так сделал и что надо было бы добавить, а то уже не знаю что ещё можно вставить.

efc6_28.08.2007_CRACKLAB.rU.tgz - xsockets.rar

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 22 сентября 2007 18:31
· Личное сообщение · #9

Я опять вернулся ... )))))) нарыл исходников , примеров и короче всеравно Жопа. Я сделал под себя пакетный протокол передачи данных ... вообщем так ...все работает просто Супер !!!!!! Парсер я взял свой старый с прошлой темы..и он у меня не глючит...как в прошлой программе ... но есть опять большое НО. Я посылаю команды серверу и все чики пики , все кроме посыла большого количества информации!!!
То есть я сформировал свой пакет с данными всеми параметрами .....к примеру в папке 100 файлов ...значит чтобы их перечислить у меня сенд будет вызван 100 раз , посыл моего пакета, пакет ограничен 1024 + 24 максимальный размер ...вообщем при вставке в листвью вставляется только 6 -7 папок ...другими словами где то чето не то . Я поставил месадж боксы на все сенды и ресивы при ошибках и нулях ...и попробывал еще раз отправить 100 папок в листвью ...пришло 6 ...но не один месадж боес не сработал , значит ошибки в сенде и ресиве нету ...когда я ставлю таймаут или месадж бокс перед вставкой все ок приходит и вставляется. У меня есть другой пример ...в этом примере нет протокола и посыл инфы идет простыми ресив и сенд ....все так же ...но почему то там вставка в листВью проходит всегда супер!!! Все вставляется . Посмотрите ПЛЗ у кого есть желание ... я отправлю в личку файлы

а ниже это то что я нарыл

NRPacket STRUCT
nrHeader db "NRP-"
nrFCode dd ?
nrPacketSeqNR dd ?
nrPacketInSeq dd ?
nrLenData dd ?
; nrDataCRC32 dd ? ; CRC32 IS NOT IMPLEMENTED AT THIS POINT
nrPointData dd ?
nrTail dd ?
NRPacket ENDS
ProcessIncoming PROC

.IF isHandshake==TRUE

INVOKE ioctlsocket, remoteDESCRIPTOR, FIONREAD, ADDR availableData
.IF eax==NULL
INVOKE GlobalAlloc, GHND, availableData
mov hMemory, eax
INVOKE GlobalLock, eax
mov offsetBuffer, eax

INVOKE recv, remoteDESCRIPTOR, offsetBuffer, availableData, 0

INVOKE StrCmp, ADDR clientID, offsetBuffer, cIDLEN
.IF eax==TRUE
mov isReliable, TRUE
mov isHandshake, FALSE

INVOKE send, remoteDESCRIPTOR, ADDR serverID, sIDLEN, 0
.IF eax==0 || eax==SOCKET_ERROR
mov eax, FALSE
.ELSE
mov eax, TRUE
.ENDIF

.IF eax==FALSE
INVOKE ShutdownSocket, socketDESCRIPTOR
INVOKE OpenSocket
.IF eax==0
mov fConn, FALSE
.ELSE
mov socketDESCRIPTOR, eax
INVOKE WSAAsyncSelect, socketDESCRIPTOR, hwnd2, WM_SOCKET, FD_ACCEPT + FD_READ + FD_CLOSE
INVOKE bind, socketDESCRIPTOR, ADDR sin, 16
INVOKE listen, socketDESCRIPTOR, 20
mov fConn, TRUE
.ENDIF
.ENDIF

.ELSE
INVOKE ShutdownSocket, socketDESCRIPTOR
INVOKE OpenSocket
.IF eax==0
mov fConn, FALSE
.ELSE
mov socketDESCRIPTOR, eax
INVOKE WSAAsyncSelect, socketDESCRIPTOR, hwnd2, WM_SOCKET, FD_ACCEPT + FD_READ + FD_CLOSE
INVOKE bind, socketDESCRIPTOR, ADDR sin, sizeof sin
INVOKE listen, socketDESCRIPTOR, 20
mov fConn, TRUE
.ENDIF

mov isHandshake, FALSE
mov receiveLOCK, FALSE
.ENDIF

INVOKE GlobalUnlock, offsetBuffer
INVOKE GlobalFree, hMemory
ret
.ENDIF
.ENDIF

.IF isReliable==TRUE

INVOKE ioctlsocket, remoteDESCRIPTOR, FIONREAD, ADDR availableData
.IF eax==NULL
.IF availableData<=1048
INVOKE recv, remoteDESCRIPTOR, ADDR packetBUFFER, availableData, 0
;invoke MessageBox,NULL,ADDR packetBUFFER,ADDR AppName,MB_OK
.ELSE
INVOKE recv, remoteDESCRIPTOR, ADDR packetBUFFER, 1048, 0
.ENDIF

; controllo header
;invoke MessageBox,NULL,ADDR packetHEAD,ADDR AppName,MB_OK
;invoke MessageBox,NULL,ADDR packetBUFFER,ADDR AppName,MB_OK
INVOKE StrCmp, ADDR packetHEAD, ADDR packetBUFFER, 4

.IF eax==TRUE

; get function code

mov esi, OFFSET packetBUFFER
add esi, 4
lodsd

push eax

.IF receiveLOCK==FALSE

mov reqOperation, eax

mov currentPacket, 0

; get total packets number & alloc buffer

mov esi, OFFSET packetBUFFER
add esi, 12
lodsd

mov totalPackets, eax
shl eax, 10

INVOKE GlobalAlloc, GHND, eax
mov hMemory, eax
INVOKE GlobalLock, eax
mov offsetBuffer, eax
mov receiveLOCK, TRUE
.ENDIF
pop eax

.IF eax==reqOperation
inc currentPacket

; get data length & copy data into buffer

mov esi, OFFSET packetBUFFER
add esi, 16
lodsd
mov ebx, currentPacket
dec ebx
shl ebx, 10
mov edi, offsetBuffer
add edi, ebx
mov ecx, eax
rep movsb

mov eax, currentPacket
.IF eax==totalPackets

; processo funzioni, dealloco buffers, receiveLOCK==FALSE

.IF reqOperation==00000000h
INVOKE проц.

.ELSEIF reqOperation==00000001h

.ENDIF

; dealloco buffers

INVOKE GlobalUnlock, offsetBuffer
INVOKE GlobalFree, hMemory

mov receiveLOCK, FALSE

.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ENDIF

INVOKE ClearBuffer, ADDR packetBUFFER, 1024+24

ret
ProcessIncoming ENDP


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 22 сентября 2007 20:05
· Личное сообщение · #10

Короче я нашел ошибку ...все чики пики. Спасибки !!!!!!! Тааак терь не раслоблятся .... готов протокол обмена. Смысл таков я посылаю пакет потом жду ответа что весь положительно пришел если да шлю дальше .. и так в цикле . Однопоточное приложение на асинхронных сокетах . Хочется многопоточное ..но тут сразу вопрос возникает ....могу ли я отправлять в потоками и получать потоками ...но при этом будет не более скажем 7 потоков и каждый поток ждет положительного ответа о доставке ....Как вы думаете это нагрузит сеть ??????? Если да то есть ли вероятность что 2 пакета пришли полностью и 3 половино только и он короче ждет до отправки ...что делать тогда ????

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube



 eXeL@B —› Программирование —› Протокол передачи (Асинхронные сокеты + динамический буфер)
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати