Текущий архив: 2006.09.24;
Скачать: CL | DM;
ВнизПомогите разобраться с сетевыми пакетами Найти похожие ветки
← →
Новичоккк (2006-09-03 10:08) [0]Есть сетевое приложение. Поставил Hook на RECV ("wsock32.dll). Вот какая информация перехватывается:
------------------
(connect)
BufferLen=2, res=2
0B 00
BufferLen=1, res=1
00
BufferLen=9, res=9
00 EB 56 85 46 5A 78 00 00
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
BufferLen=2, res=2
12 00
BufferLen=1, res=1
2B
BufferLen=16, res=16
2B 9C 17 A8 1A 09 D6 79 55 04 A4 C1 6D 08 E1 F5
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
(disconnect)
------------------
Реально же с сервера приходит 2 пакета, после чего происходит разъединение... Пакеты:
#1:
0B 00 00 EB 56 85 46 5A 78 00 00
#2:
12 00 2B 9C 17 A8 1A 09 D6 79 55 04 A4 C1 6D 08 E1 F5
Почему так происходит? Никак не могу разобраться.
Забыл сказать, что по протоколу первые два байта пакета - его длина. Это объясняет почему клиент сначала считывает 2 байта... но зачем он читает еще один байт, а потом уже только всю оставшуюся часть пакета? Почему этот байт, который он уже считал, приходит еще раз, включенный в "оставшуюся часть"? Ведь он уже был считан... никак не могу этого понять.
И еще, насколько я понял "Result=-1" - клиент делает запрос информации, но её еще нет.
Надеюсь на вашу помощь
← →
Новичоккк (2006-09-03 10:09) [1]И еще... почему происходит вот так:
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
BufferLen=2, res=-1
BufferLen=1, res=-1
Если по идее он должен ждать прихода 2х байт??? А реально запрашивает то 1, то 2...
← →
Ketmar © (2006-09-03 11:11) [2]как хочет -- так и читает. а у тебя явно ошибки в коде, ибо после "res=-1" ничего уже прийти не может -- это disconnect.
← →
Новичоккк (2006-09-03 11:26) [3]
TLogData = record
FuncName: String[8];
IP: String[15];
Port: Cardinal;
Buff: array [0..$FFFF] of Char;
BuffSize: Integer;
end;function NewRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
type
TrecvImage = function(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
var
SockAddr: TSockAddr;
AddrLen: Integer;
Data: TLogData;
pck: string;
begin
Result := TrecvImage(OldRecv)(s, Data.Buff[0], len, flags);
if getpeername(s, SockAddr, AddrLen) = SOCKET_ERROR then Exit;
Data.IP := inet_ntoa(SockAddr.sin_addr);
Data.Port := ntohs(SockAddr.sin_port);
Data.BuffSize := Result;
PrintText(PChar("len="+IntToStr(len)+", res="+IntToStr(Data.BuffSize)));
if Data.BuffSize<>-1 then
begin
SetLength(pck, Data.BuffSize);
Move(Data.Buff[0], pck[1], Data.BuffSize);
PrintPacket(pck);
end;
Move(Data.Buff[0], Buf, Result)
...
end;
По-моему всё правильно
← →
Ketmar © (2006-09-03 12:14) [4]как минимум вижу несколько багов и полубагов:
* какой размер у data.Buff[]? и зачем он вообще? почему не использовать buf, который программа уже предоставила?
* кто тебе дал право вызывать getpeername()? думаешь, реальное значение WSAGetLastError() ни одной программе не нужно?
* результат может быть и нулевым, кстати.
* если использовать собственно buf, то отпадёт необходимость в последнем Move().
* что, проверять, не равно ли flags MSG_PEEK (как минимум) -- это барство?
* почему не взять WinPCap? %-)
← →
Новичоккк (2006-09-03 18:30) [5]* Data.Buff - 0..$FFFF
Пытался раньше использовать buf - в любом случае приложение просто вылетало (может что не так делал...). Как правильно читать из этого буффера?
* Получается в таком случае не возможно узнать Port (если не использовать getpeername)?
* Спасибо за подсказку с MSG_PEEK. Скорей всего приложение считывает этот самый один байт с этим флагом (поэтому он и отправляется по второму разу в следующей партии)
А вообще код писал по примеру от Rouse_
(http://forum.sources.ru/index.php?showtopic=86903)
← →
Ketmar © (2006-09-03 19:31) [6]> [5] Новичоккк (03.09.06 18:30)
так и читать. например, описать его какbuf: PAnsiChar;
.
Страницы: 1 вся ветка
Текущий архив: 2006.09.24;
Скачать: CL | DM;
Память: 0.46 MB
Время: 0.05 c