Показать полную графическую версию : Подсчет траффик на Delphi
Помогите написать подсчет траффик на Delphi... Я бы хотел чтобы она могла считать и локальный и глобальный траффик. Киньте сорцы или дайте линк плиз...
Мне надо чтобы программа просто перехватывала траффик с подключения. Как это сделать? :(
Netscaper
20-12-2004, 16:39
#include <conio.h>
#include <stdio.h>
#include <winsock2.h>
#define MAX_PACKET_SIZE 0x10000
#define SIO_RCVALL 0x98000001
// Буфер для приёма данных
char Buffer[MAX_PACKET_SIZE]; // 64 Kb
//Структура заголовка IP-пакета
typedef struct IPHeader {
UCHAR iph_verlen; // версия и длина заголовка
UCHAR iph_tos; // тип сервиса
USHORT iph_length; // длина всего пакета
USHORT iph_id; // Идентификация
USHORT iph_offset; // флаги и смещения
UCHAR iph_ttl; // время жизни пакета
UCHAR iph_protocol; // протокол
USHORT iph_xsum; // контрольная сумма
ULONG iph_src; // IP-адрес отправителя
ULONG iph_dest; // IP-адрес назначения
} IPHeader;
char src[10];
char dest[10];
char ds[15];
unsigned short lowbyte;
unsigned short hibyte;
void main()
{
WSADATA wsadata; // Инициализация WinSock.
SOCKET s; // Cлущающий сокет.
char name[128]; // Имя хоста (компьютера).
HOSTENT* phe; // Информация о хосте.
SOCKADDR_IN sa; // Адрес хоста
IN_ADDR sa1; //
unsigned long flag = 1; // Флаг PROMISC Вкл/выкл.
// инициализация
WSAStartup(MAKEWORD(2,2), &wsadata);
s = socket( AF_INET, SOCK_RAW, IPPROTO_IP );
gethostname(name, sizeof(name));
phe = gethostbyname( name );
ZeroMemory( &sa, sizeof(sa) );
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[0])->s_addr;
bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR));
// Включение promiscuous mode.
ioctlsocket(s, SIO_RCVALL, &flag);
// Бесконечный цикл приёма IP-пакетов.
while( !_kbhit() )
{
int count;
count = recv( s, Buffer, sizeof(Buffer), 0 );
// обработка IP-пакета
if( count >= sizeof(IPHeader) )
{
IPHeader* hdr = (IPHeader *)Buffer;
//Начинаем разбор пакета...
strcpy(src,"Пакет: ");
CharToOem(src,dest);
printf(dest);
// Преобразуем в понятный вид адрес отправителя.
printf("From ");
sa1.s_addr = hdr->iph_src;
printf(inet_ntoa(sa1));
// Преобразуем в понятный вид адрес получателя.
printf(" To ");
sa1.s_addr = hdr->iph_dest;
printf(inet_ntoa(sa1));
// Вычисляем протокол. Полный список этих констант
// содержится в файле winsock2.h
printf(" Prot: ");
if(hdr->iph_protocol == IPPROTO_TCP) printf("TCP ");
if(hdr->iph_protocol == IPPROTO_UDP) printf("UDP ");
// Вычисляем размер. Так как в сети принят прямой порядок
// байтов, а не обратный, то прийдётся поменять байты местами.
printf("Size: ");
lowbyte = hdr->iph_length>>8;
hibyte = hdr->iph_length<<8;
hibyte = hibyte + lowbyte;
printf("%s",itoa(hibyte,"",10));
// Вычисляем время жизни пакета.
printf(" TTL:%s",itoa(hdr->iph_ttl,"",10));
printf("\n");
}
}
closesocket( s );
WSACleanup();
}
Для успешной компиляции, необходимо подключить к проекту файл ws2_32.lib. :insane:
Netscaper
20-12-2004, 16:42
(C) Ishodnik.ru (http://ishodniki.ru/list/info.php?cat=6&id=1154&show=cpp_network)... Подумал... Так... Для справки :)
Netscaper
Блин... вроде это на С++ :)
А на этом сайте нету кода на дельфи :(
Я в С++ вообще не соображаю, если кто сможет переписать плз :)
Netscaper
20-12-2004, 18:09
Я перепишу на Delphi как только время появится... Завтра, скорее.
Netscaper
Ок спасибо огромное. Ты настоящий друг :)
Netscaper
21-12-2004, 01:09
Держи. Конечно, в Delphi такое лучше не делать - мозги свернешь...
Рабочая консольная версия. Всё же рекомендуется поизучать socket'ы.
У меня вроде работает... Оказывается в сетке два компа broadcast шлют, может, игровые серверы?
program Sniffer;
// Translated by Netscaper :)
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, WinSock;
const
// Максимальный размер пакета
MaxPacketSize = 65536;
// Принимаем все пакеты
SIO_RCVALL = $98000001;
type
// Список адресов машины
PInAddrList = ^TInAddrList;
TInAddrList = Array[0..255] of PInAddr;
// Заголовок Ip4
PIPHeader = ^TIPHeader;
TIPHeader = record
verlen, tos : Byte;
length, id, offset : Word;
ttl, protocol : Byte;
xsum : Word;
src, dest : Cardinal;
end;
// Получаем IP-адрес (ненавижу PChar и inet_ntoa)
function get_ip4(ip4 : Cardinal): string;
begin
Result := IntToStr(Lo(LoWord(ip4))) + '.' +
IntToStr(Hi(LoWord(ip4))) + '.' +
IntToStr(Lo(HiWord(ip4))) + '.' +
IntToStr(Hi(HiWord(ip4)));
end;
var
// практически всё то же, что и на C++
hdr : PIPHeader;
buffer : Array[0..MaxPacketSize - 1] of byte;
wsa : WSADATA;
s, size : Integer;
hostname : Array[0..127] of char;
phe : Phostent;
sa : sockaddr_in;
flag : Integer;
Len : Word;
outstr : String;
inaddrlist : PInAddrlist;
begin
flag := 1;
// Иницилизируем
WSAStartup(2, wsa);
s := socket(AF_INET, SOCK_RAW, IPPROTO_IP);
// Получаем название нашего хоста
gethostname(@hostname, 128);
// Получаем информацию о хосте
phe := gethostbyname(@hostname);
FillChar(sa, sizeof(sa), 0);
inaddrlist := PInAddrList(phe.h_addr_list);
// Привязываемся к нашему сокету :)
sa.sin_family := AF_INET;
sa.sin_addr.S_addr := inaddrlist^[0].S_addr;
if (bind(s, sa, sizeof(sa)) = SOCKET_ERROR) then
begin
// Ошибка
flag := WSAGetLastError;
writeln('bind fails.result=',flag);
readln;
halt;
end;
// Выбираем режим "прослушки"
ioctlsocket(s, SIO_RCVALL, flag);
while(true) do
begin
// Ждем пакет :)
size := recv(s, Buffer, sizeof(Buffer), 0);
if (size = SOCKET_ERROR) then
begin
// Бывают же глюки :)
flag := WSAGetLastError; break;
end;
// Если пакет имеет размер с заголовок или больше, то это - хорошо :)
if (size >= sizeof(TIPHeader)) then
begin
// Печатаем
hdr := PIPHeader(@Buffer);
outstr := 'Packet from ' + get_ip4(hdr.src) +
' to ' + get_ip4(hdr.dest) + ', protocol ';
if hdr.protocol = IPPROTO_TCP then outstr := outstr + 'TCP';
if hdr.protocol = IPPROTO_UDP then outstr := outstr + 'UDP';
outstr := outstr + ', size ';
Len := hdr.length shl 8 + hdr.length shr 8;
outstr := outstr + IntToStr(Len) + ', TTL ' + IntToStr(hdr.ttl);
writeln(outstr);
end;
end;
// Теоретически, у нас бесконечный цикл, но после использования лучше
// закрыть сокет и освободить WS2_32.DLL
writeln('flag=',flag);
readln;
closesocket(s);
WSACleanup;
end.
Netscaper Нда уж... тут ты прав (про мозги) :)
Сейчас попробую.. спасибо.
Если кто-нибудь найдет другую реализацию, пожалуйста выкладывайте сюда :)
Netscaper
21-12-2004, 12:23
В чём проблема? Нельзя сосчитать исходящий/входящий трафик? Сделай фильтр по нужным хостам.
Netscaper
Да нет, все ок... впринципе можно сделать все :)
Перепишу только ее под форму и тогда вообще ок будет..
Просто может быть у кого-нибудь есть еще варианты :)
У меня вот еще вопрос... размер пакета указывается ведь в байтах?
Netscaper
21-12-2004, 13:56
Разумеется, всё в байтах. Лучше запихни обработку в отдельный Thread, а то у тебя же тогда накроется основной поток, т.к. recv ожидает пакеты, т.е. во время ожидания будет «накрывать» основной поток.
Netscaper
Что-то у меня не получается под форму засунуть :((((((((((
Netscaper
21-12-2004, 14:30
В плане?
Netscaper
21-12-2004, 14:47
Вот, то же самое, только на Delphi c окошками.
[Вложение удалено]
Netscaper
Ок спасибо, сейчас посмотрю
Аааааа :) все донал...
Слушай... дак тут пакеты то не только которые идут ко мне... тут вообще какие-то левые пакеты?!
Или это все пакеты идут ко мне?
Хм... а как мне ловить не сетевой траффик, а инетовский? :)
Сори если надоел... я программер самоучка ;)
Netscaper
21-12-2004, 16:29
Естественно, мне тоже. Оставляй те, которые идут от тебя или к тебе. Инетовский очень просто - трафик на шлюз или прокси (конкрентный компьютер в сети).
Netscaper
Ок. Ясно. Пойду пробовать, если что напишу :)
Кст. А как отфильтровать на себя или от себя?
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.