Например сделать так, если промежуток между сообщениями меньще 3 сек. - kick. Я смог реализовать токо один способ, но он с проблемами. Если кто-то пишет в чате, бот проверяет, если нету, то заводит структуру на этот ник и присоединяет к массиву структур, вот так: Код (Text): ACCAUNTINFO struct NickLen dd ? NickBuf dd ? MinBuf dd ? SecBuf dd ? NextLink dd ? ACCAUNTINFO ends NumArray dd 256 dup(?) szTime db "mmss",0 AddNickStruct proc scr:dword local buffer[128]:byte invoke lstrlen,scr push eax lea esi,buffer mov edi,scr mov ecx,eax @@: mov al,byte ptr [edi] mov byte ptr [esi],al inc esi inc edi dec ecx jnz @B mov byte ptr [esi],0 invoke GlobalAlloc,0h or 40h,sizeof ACCAUNTINFO mov esi,eax assume esi:ptr ACCAUNTINFO pop eax mov [esi].NickLen,eax mov [esi].MinBuf,0 mov [esi].SecBuf,0 invoke GlobalAlloc,0h or 40h,eax mov [esi].NickBuf,eax invoke lstrcpy,[esi].NickBuf,addr buffer mov eax,offset NumArray movzx edx,byte ptr [buffer] shl edx,2 add eax,edx .if dword ptr [eax]==0 mov dword ptr [eax],esi .else push dword ptr [eax] pop [esi].NextLink mov dword ptr [eax],esi .endif assume esi:nothing ret AddNickStruct endp ; А сама процедура сравнения выглядит так AntiFlood proc scr:dword local hYes:dword local AddNick[128]:byte local TimeBuf[256]:byte local _min[4]:byte local _sec[4]:byte invoke lstrcpy,addr AddNick,scr mov hYes,0 lea esi,AddNick invoke lstrlen,esi mov edx,eax movzx ebx,byte ptr [esi] shl ebx,2 add ebx,offset NumArray .if dword ptr [ebx]!=0 mov ebx,dword ptr [ebx] assume ebx:ptr ACCAUNTINFO .while ebx!=0 .if edx==[ebx].NickLen push edx push ebx invoke lstrcmpi,[ebx].NickBuf,esi .if eax==0 mov hYes,1 invoke GetTimeFormat,0,TIME_FORCE24HOURFORMAT,0,offset szTime,addr TimeBuf,256 mov al,byte ptr [TimeBuf+0] mov byte ptr [_min+0],al mov al,byte ptr [TimeBuf+1] mov byte ptr [_min+1],al invoke atodw,addr _min ; получаем минуты pop ebx pop edx .if eax == [ebx].MinBuf ; если равно получаем секунды mov al,byte ptr [TimeBuf+2] mov byte ptr [_sec+0],al mov al,byte ptr [TimeBuf+3] mov byte ptr [_sec+1],al invoke atodw,addr _sec ; получаем секунды mov edx,eax sub edx,[ebx].SecBuf ; отнимаем от нынешнего прошедшую .if edx < 3 ; если разница меньще 3 сек - кикаем push ebx ;kick pop ebx mov [ebx].NickLen,0 mov [ebx].MinBuf,0 mov [ebx].SecBuf,0 invoke GlobalFree,[ebx].NickBuf .else mov [ebx].SecBuf,eax ; присвоиваем .endif .else mov [ebx].MinBuf,eax ; если не равно, присвоиваем .endif .break .endif pop ebx pop edx .endif mov ebx,[ebx].NextLink .endw assume ebx:nothing .endif .if hYes != 1 ; если нет такого чуловека, добавляем invoke AddNickStruct,addr AddNick .endif ret AntiFlood endp Хотю заметит что подпрограмма составления структурных массивов и их сравнения принадлежат дяденьке Iczelion'у, я просто под себя подкоректировал.. Есть проблемка, если много рас вызвать GlobalAlloc, прога выдаёт ошибку и падает.. Помогите плиз либо улучшить этот вариант, либо слушаю ваши алгоритмы по решению данной задачи... Спасибо!
Так будет гораздо проще. И быстрее. Код (Text): AddNickStruct proc scr:dword invoke HeapAlloc, hHeap, 0, sizeof ACCAUNTINFO mov esi, eax assume esi:ptr ACCAUNTINFO invoke lstrlen, scr mov [esi].NickLen,eax inc eax invoke HeapAlloc, hHeap, 0, eax mov [esi].NickBuf, eax invoke lstrspy, eax, scr mov [esi].MinBuf,0 mov [esi].SecBuf,0 ; Дальше что-то непонятное делаем с первой буквой ника... структура ACCAUNTINFO не совсем понятна что такое MinBuf, SecBuf, NextLink? Я так понял, что у тебя односвязный список и указатель на стедующую структуру лежит в NextLink? А где лежит указатель на первую структуру? mov eax,offset NumArray movzx edx,byte ptr [buffer] - тут код первая буква ника shl edx,2 add eax,edx .if dword ptr [eax]==0 - если NumArray[первая буква ника] == 0 mov dword ptr [eax],esi - вносим туда указатель на созданную структуру .else push dword ptr [eax] - иначе в NextLink структуры вносим NumArray[ник] pop [esi].NextLink mov dword ptr [eax],esi - а в NumArray[ник] - указатель на созданную структуру .endif Ничерта тут не понял...
Тут мало общего с твоей задачей, и адаптировать готовое решение к твоей задаче - слишком сложный и неоправданый труд. Ессно это IMHO, но на твоем месте я бы сделал приблизительно так: Код (Text): .data ACCOUNTINFO struct szNick db 64 dup (?) ; никогда не видел ников, длиннее 63 символов LastMessageTime dd ? ; а тут - время отправки последнего сообщения next dd ? ; указатель на структуру следующего пользователя ACCOUNTINFO ends hHeap dd 0 pFirstAccount dd 0 Код (Text): ; Процедура сравнения ников CheckName proc uses ecx esi edi pszNick:PCHAR, pAccount:ptr ACCOUNTINFO xor ecx, ecx mov esi, pszNick mov edi, pAccount .while (ecx<32 && BYTE ptr [esi+ecx]>0) mov al, BYTE ptr [esi+ecx] .if (al!=BYTE ptr [edi+ecx]) .break .endif inc ecx .endw xor eax, eax .if(ecx==32) inc eax .endif ret CheckName endp Код (Text): ; Вызываем при каждом сообщении CheckUser proc pszNick:PCHAR local TimeStamp:DWORD invoke GetTickCount mov TimeStamp, eax mov esi, pFirstAccount assume esi:ptr ACCOUNTINFO assume edi:ptr ACCOUNTINFO xor edi, edi .while(esi!=NULL) invoke CheckName, pszNick, esi .if(eax!=0) .break .endif mov edi, esi mov esi, [esi].next .endw .if(esi==NULL) invoke HeapAlloc, hHeap, 0, sizeof ACCOUNTINFO mov esi, eax .if(edi!=NULL) mov [edi].next, esi .else mov pFirstAccount, esi .endif mov eax, TimeStamp mov [esi].LastMessageTime, eax mov [esi].next, 0 invoke lstrcpyn, [esi].szNick, pszNick, 64 .else mov eax, TimeStamp sub eax, [esi].LastMessageTime .if(eax>3000) invoke KickUser, pszNick ; еще тут можно освободить память под структуру кикнутого юзверя, если хочеш ; ну и пересвязять односвязный список, ессно .endif mov eax, TimeStamp mov [esi].LastMessageTime, eax .endif assume edi:nothing assume esi:nothing ret CheckUser endp Ошибок тут наверно немеряно, писал на скорую руку и не проверил. Думаю розберешся.
Увы, не смог Рас стоко строк писал ради того чтоб помочь хотяб разок пропустил через компилятор.. А то вроди и с сравнением проблемы, и в области lstrcpyn. Чувствую и HeapAlloc будет выдавать ошибки при многократном вызове. По большёму счёту ты сделал тоже самое... Iczelion'овский вариант быстрее. Благодаря твоему примеру теперь в том варианте память под ник не выделяю, и это гуд, осталось как-нить справиться с памятью под структуру, есть идеи ?
В сравнении ников все 32 надо поменять на 64 и конечный if поправить. Структура ACCOUNTINFO занимает 72 байта. На каждый мегабайт оперативы влазит 14563 юзверя. Не пойму что за проблемы с выделением памяти.
Код (Text): CheckName proc uses ecx esi edi pszNick:PCHAR, pAccount:ptr ACCOUNTINFO xor ecx, ecx mov esi, pszNick mov edi, pAccount .while (ecx<32 && BYTE ptr [esi+ecx]>0) mov al, BYTE ptr [esi+ecx] .if (al!=BYTE ptr [edi+ecx]) jmp NotEqual .endif inc ecx .endw xor eax, eax inc eax ret NotEqual: xor eax, eax ret CheckName endp ну если не нравится 64, то делай Код (Text): invoke lstrlen, pszNick invoke lstrcpyn, [esi].szNick, pszNick, eax Это все лень...
Имхо, проще всего пройти в отладчике код и посмотреть, сколько там памяти выделилось при первом, втором добавлении...
аха, лень.., спасибо за помощь. кстати, и знак надо поменять .if(eax>3000), а то потестил, все кто что-то говорил - кикало ) долго размышлял над этим