Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.20;
Скачать: CL | DM;

Вниз

Помогите с сокетом   Найти похожие ветки 

 
V@LER@N ©   (2004-04-26 15:39) [0]

Всем доброго времени суток. Есть такая трабла: как смастерить програмулину, которая, работая в ЛАНе (5 компов) на одной из машин, могла бы получать инфу, к-рая приходит на эту машину с других. Пытался писАть на стандартных сокетах - ничего не получилось:(. Смущает такая вещь как "порт" - каков его смысл и где взять его значение я так и не расчехлил. Пробовал переделать один из снифферов (пример Verg"a) - запутался еще сильнее. Сам сниффер у меня работать не стал. Там было сказано, что это только пример, а не рабочая прога, но хоть какие-то признаки жизни он подавать должен был...


 
Digitman ©   (2004-04-26 18:09) [1]


> Пытался писАть на стандартных сокетах


что есть "стандартных сокетах" ?


> Сам сниффер у меня работать не с


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


 
Polevi ©   (2004-04-27 08:18) [2]

снифер он пишет, ты бы еще с TDI начал чтоли


 
имя   (2004-04-27 08:21) [3]

Удалено модератором


 
V@LER@N ©   (2004-04-27 17:29) [4]

Удалено модератором
Примечание: Оффтоп...


 
Digitman ©   (2004-04-27 17:42) [5]

Удалено модератором
Примечание: Оффтоп...


 
VMcL ©   (2004-04-27 17:46) [6]

Удалено модератором
Примечание: Все что ниже удалено - оффтоп...


 
Digitman ©   (2004-04-27 17:48) [7]

Удалено модератором


 
Digitman ©   (2004-04-27 18:00) [8]

Удалено модератором


 
V@LER@N ©   (2004-04-27 18:14) [9]

Удалено модератором


 
Digitman ©   (2004-04-27 18:21) [10]

Удалено модератором


 
Piter ©   (2004-04-27 19:25) [11]

Удалено модератором


 
Verg ©   (2004-04-27 20:56) [12]


> Заново писать не буду, так как сижу в инет-кафе, а по памяти
> написать не смогу... Он у меня зависает на вызове recv.
> Почему?


По памяти, насколько я помню, люди которые на самом деле решили его попробовать обычно спрашивали: "чему равна константа SIO_RCVALL" и кто такой модуль mstсpip, winsock2? Просто интересно, почему у тебя таких вопросов не возникает?

Кстати, ты знаешь, что в сетях Microsoft Windows информация может передаваться не только с применением IP-базирующихся протоколов?
SOCK_RAW, тем временем может принимать (передавать) ТОЛЬКО IP датаграммы.


 
Verg ©   (2004-04-27 21:25) [13]

В качестве развлечения (появился часок другой св. вр.), предлагаю продолжить тему консольных сниферов, т.е. модорнизацию их уже на более кокретные, полезные цели. Считаю себя вправе выбрать тему для такого развлечения и начинаю с метафоры.
Пусть нам хочется узнать интенсивность потребления TCP - трафика некоего хоста в нашей (а в слчаях транзитных сетей возможно и не нашей) сети. Т.е. надо узнать с какой интенсивностью некий хост (Target IP) принимает TCP трафик. Для чего? Ну, например, для того, чтобы предсказать его на будущее и указать, например, на черезмерность. Но главное - иллюстрация работы не столько даже SOCK_RAW, сколько понимание что и где лежит в IP пакетах вместе с надстроенным протоколом верхнего уровня (в данном случае - TCP)
К тому же давайте учтем, что при некоторых условиях пиковая скорость поступления TCP/IP потока (сегментов) очень высока. ..... я думаю, что нужно бы оценить справляется наш "счетчик" или нет.

Итак, первое, что приходит в голову - это необходимость создать модуль, который описывал структуры данных приходящих к нам с SOCK_RAW.

Итак, назовем его IpUtils.pas

unit IPUtils;

interface
uses Windows, WinSock2;

const
 IP_MAXPACKET = high(word);

type
   // IP header
   PIPHeader = ^TIPHeader;
   TIPHeader = packed record
     verlen : byte;      // версия и длина заголовка
     tos    : byte;      // тип сервиса
     length : word;      // длина всего пакета
     id     : word;      // Id
     offset : word;      // флаги и смещения
     ttl    : byte;      // время жизни
     protocol : byte;    // протокол
     xsum   : word;      // контрольная сумма
     src    : TInAddr;   // IP-адрес отправителя
     dst    : TInAddr;   // IP-адрес назначения
   end;

   // TCP Header
   TTCPHeader = packed record
     Source:        word;  //Source Port
     Destination:   word;  //Destination Port
     Seq:           ulong; // порядковый номер передаваемого октета
     Ack:           ulong; // порядковый номер принятого октета
     Rsvd0_Off:     byte;  //Смещение до начала данных
     Flags_Rsvd1:   byte;  //флаги
     Window:        word;  // Размер окна
     Checksum:      word;
     UrgPoint:      word;
   end;
   PTCPHeader = ^TTCPHeader;

   //Флаги TCP (TTCPHeader.Flags_Rsvd1)
   const
     TCP_FLAG_FIN = $01;
     TCP_FLAG_SYN = $02;
     TCP_FLAG_RST = $04;
     TCP_FLAG_PSH = $08;
     TCP_FLAG_ACK = $10;
     TCP_FLAG_URG = $20;

function net_checksum( var data; len : word):word;
function net_chksum_add( S1, S2 : word ) : word;
function PHCheckSumm(Src, Dst : TInAddr;
                    Proto: byte;
                    Len : word):word;

implementation
uses SysUtils;

type
   // Псевдозаголовок
   TPSUHeader = packed record
     Src:        TInAddr;
     Dst:        TInAddr;
     Zero:       byte;
     Protocol:   byte;
     Length:     word;
   end;
   PPSUHeader = ^TPSUHeader;

function net_checksum( var data; len : word):word;
var
  Sum : ulong;
  Dp  : PWORD;
  Words : integer;
begin
   Sum := 0;
   Dp := PWORD(@Data);
   for Words := 1 to Len shr 1 do
   begin
     sum := sum + dp^;
     inc(Dp);
   end;
   if odd(len) then
     Sum := Sum + ord(pchar(Dp)^);
   Sum := (Sum and $FFFF) + LongRec(Sum).Hi;
   Result:= LongRec(sum).Lo + LongRec(Sum).Hi;
   if Result <> $FFFF then
     Result := not Result;
end;

function net_chksum_add( S1, S2 : word ) : word;
var
 Sum : ulong;
begin
 Sum := ulong(s1) + ulong(s2);
 result := Sum;
 if LongRec(Sum).Hi <> 0 then
   Sum := Result + 1
 else
   Sum := Result;
 if (Sum = 0) and ((S1 or S2) <> 0) then
   result := $FFFF
 else
   result := Sum;
end;

function PHCheckSumm(Src, Dst : TInAddr;
                    Proto: byte;
                    Len : word):word;
var pH : TPSUHeader;
begin
 pH.Src := src;
 pH.Dst := dst;
 pH.Protocol := Proto;
 pH.Zero := 0;
 pH.Length := htons(Len);
 result := net_checksum(pH, sizeof(pH));
end;

end.

Думаю, что будет достаточно для модуля такого предназначения...

to be continued...


 
Verg ©   (2004-04-27 21:36) [14]

Теперь, стоит вспонить, что SOCK_RAW может работать в режиме "сковзного приема" (SIO_RCVALL) только с локальным адресом  совпадающим с IP адресом какого-то одного, конкретного, реально физически существующего сетевого интерфейса (сетевого адаптера). Т.е. такому сокету нельзя назначить локальный адрес типа INADDR_ANY (0.0.0.0) или INADDR_LOOPBACK (127.0.0.1).
Т.о., если мы решили "наблюдать" за IP трафиком идущим в сторону конкретоного адрес, то мы должы из, в общем случае, множества сетевых адаптеров на нашем компе определить такой, который быдет в состоянии принимать (слышать) пакеты адресованные Target IP. Я предпочитаю для этого пользоваться замечательной библиотекой iphlpapi.dll, поэтому надо создать минимальный интерфейсный модуль для использования ее возможностями.
unit IPHelper;

interface
uses Windows;
const
 MAX_INTERFACE_NAME_LEN  = 256;
 MAX_TRANSPORT_NAME_LEN  = 40;
 MAX_MEDIA_NAME          = 16;
 MAX_PORT_NAME           = 16;
 MAX_DEVICE_NAME         = 128;
 MAX_PHONE_NUMBER_LEN    = 128;
 MAX_DEVICETYPE_NAME     = 16;
 MAXLEN_IFDESCR          = 256;
 MAXLEN_PHYSADDR         = 8;

type
 TIPAddr = ULONG;     // An IP address.
 TIPMask = ULONG;     // An IP subnet mask.
 TIP_STATUS = ULONG;  // Status code returned from IP APIs.

   TMIB_IFROW = record
           wszName : array[0..MAX_INTERFACE_NAME_LEN-1] of widechar;
           dwIndex,
           dwType,
           dwMtu,
           dwSpeed,
           dwPhysAddrLen : DWORD;
           bPhysAddr : array[0..MAXLEN_PHYSADDR-1] of BYTE;
           dwAdminStatus,
           dwOperStatus,
           dwLastChange,
           dwInOctets,
           dwInUcastPkts,
           dwInNUcastPkts,
           dwInDiscards,
           dwInErrors,
           dwInUnknownProtos,
           dwOutOctets,
           dwOutUcastPkts,
           dwOutNUcastPkts,
           dwOutDiscards,
           dwOutErrors,
           dwOutQLen,
           dwDescrLen : DWORD;
           bDescr : array[0..MAXLEN_IFDESCR-1] of BYTE;
end;

PMIB_IFROW = ^TMIB_IFROW;

const
 MIB_IF_TYPE_OTHER              = 1;
 MIB_IF_TYPE_ETHERNET           = 6;
 MIB_IF_TYPE_TOKENRING          = 9;
 MIB_IF_TYPE_FDDI               = 15;
 MIB_IF_TYPE_PPP                = 23;
 MIB_IF_TYPE_LOOPBACK           = 24;
 MIB_IF_TYPE_SLIP               = 28;

 MIB_IF_ADMIN_STATUS_UP         = 1;
 MIB_IF_ADMIN_STATUS_DOWN       = 2;
 MIB_IF_ADMIN_STATUS_TESTING    = 3;

 MIB_IF_OPER_STATUS_NON_OPERATIONAL =     0;
 MIB_IF_OPER_STATUS_UNREACHABLE     =     1;
 MIB_IF_OPER_STATUS_DISCONNECTED    =     2;
 MIB_IF_OPER_STATUS_CONNECTING      =     3;
 MIB_IF_OPER_STATUS_CONNECTED       =     4;
 MIB_IF_OPER_STATUS_OPERATIONAL     =     5;

type
 
TMIB_IFTABLE = record
   dwNumEntries : DWORD;
   table        : array[0..0] of TMIB_IFROW;
end;
PMIB_IFTABLE = ^TMIB_IFTABLE;

TMIB_IPADDRROW = record
   dwAddr,
   dwIndex,
   dwMask,
   dwBCastAddr,
   dwReasmSize : DWORD;
   unused1,
   unused2 : WORD;
end;
PMIB_IPADDRROW = ^TMIB_IPADDRROW;

TMIB_IPADDRTABLE = record
 dwNumEntries : DWORD;
 table        : array[0..0] of TMIB_IPADDRROW;
end;
PMIB_IPADDRTABLE= ^TMIB_IPADDRTABLE;

TMIB_IPFORWARDROW = record
 dwForwardDest     : DWORD;
 dwForwardMask     : DWORD;
 dwForwardPolicy   : DWORD;
 dwForwardNextHop  : DWORD;
 dwForwardIfIndex  : DWORD;
 dwForwardType     : DWORD;
 dwForwardProto    : DWORD;
 dwForwardAge      : DWORD;
 dwForwardNextHopAS : DWORD;
 dwForwardMetric1   : DWORD;
 dwForwardMetric2   : DWORD;
 dwForwardMetric3   : DWORD;
 dwForwardMetric4   : DWORD;
 dwForwardMetric5   : DWORD;
end;
PMIB_IPFORWARDROW = ^TMIB_IPFORWARDROW;

const
   MIB_IPROUTE_TYPE_OTHER   = 1;
   MIB_IPROUTE_TYPE_INVALID = 2;
   MIB_IPROUTE_TYPE_DIRECT  = 3;
   MIB_IPROUTE_TYPE_INDIRECT= 4;

type
TMIB_IPFORWARDTABLE = record
 dwNumEntries  : DWORD;
 table         : array[0..0] of TMIB_IPFORWARDROW;
end;
PMIB_IPFORWARDTABLE = ^TMIB_IPFORWARDTABLE;

function   GetIfTable(pIfTable : PMIB_IFTABLE; var pdwSize : ULONG; bOrder : BOOL): DWORD; stdcall;

function GetIpAddrTable(pIpAddrTable : PMIB_IPADDRTABLE; var pdwSize : ULONG; bOrder : BOOL): DWORD; stdcall;

function SendARP(DestIP:DWORD;SrcIP:DWORD; var pMacAddr; var PhyAddrLen:DWORD):DWORD;stdcall;

function  SetIfEntry(pIfRow : PMIB_IFROW   // specifies interface and status
): DWORD; stdcall;

function GetIpForwardTable(
 pIpForwardTable : PMIB_IPFORWARDTABLE;  // buffer for routing table
 var pdwSize : ULONG;                       // size of buffer
 bOrder : BOOL                          // sort the table
): DWORD; stdcall;

function GetBestInterface(
 dwDestAddr : DWORD;     // destination IP address
 var pdwBestIfIndex : DWORD // index of interface with the best route
) : DWORD; stdcall;

function GetIfEntry(var pIfRow : TMIB_IFROW ): DWORD; stdcall;  // pointer to interface entry

function NotifyRouteChange(var Handle : THandle; var overlapped : TOverlapped):DWORD; stdcall;

implementation

function   GetIfTable;       external "IPHLPAPI.DLL";
function   GetIpAddrTable;   external "IPHLPAPI.DLL";
function   SendARP;          external "IPHLPAPI.DLL";
function   SetIfEntry;       external "IPHLPAPI.DLL";
function   GetIpForwardTable;external "IPHLPAPI.DLL";
function   GetBestInterface; external "IPHLPAPI.DLL";
function   GetIfEntry;       external "IPHLPAPI.DLL";
function   NotifyRouteChange;external "IPHLPAPI.DLL";

end.


 
Verg ©   (2004-04-27 21:48) [15]

Так, теперя, я думаю, будет полезным иметь возможность считать не просто интенсивность входящего TCP/IP трафика, а с какого-то конкретого,заданного порта. Хм... Представилось,  как некий комп в итрасети (бынальные 192.168......) качает из интернента через прокси (другого пути в интернет у него просто нет). Значит, задав известный порт прокси (например, 3128) мы можем селектировать именно такой трафик....
Впрочем, давайте условимся, что если в качесве порта будет задано значение 0 (ноль), то мы будем считать трафик с любого порта источника без разбору.


 
Verg ©   (2004-04-27 21:56) [16]

Проблемка чисто математического плана: если наш проц достаточно быстр и быстр на столько, что время обработки датаграммы почти не зависит от ее размера, то получится по-моему обман, если мы будем усреднять скорость обработки поступающей информации, складывая их объем и деля на суммароне время обработки каждой в условиях множества малых пакетов.
Ну что ж, введем понятия "малой" датаграммы и не будем учитывать в расчете средней производительности датаграммы "нулевого" размера.


 
Verg ©   (2004-04-27 22:03) [17]

Да, чтобы пока нескучно было :) качайте Winsock2.pas, с молчаливого разрешения (я надеюсь) Alex Konshin-а :)
http://home.earthlink.net/~akonshin/files/ws2rev4a.zip
И еще модуль
unit mstcpip;

interface
uses Winsock2;
type
   _tcp_keepalive  = packed record
      onoff : u_long;
      keepalivetime : u_long;
      keepaliveinterval : u_long;
   end;

const
// New WSAIoctl Options
SIO_RCVALL                           = IOC_IN or IOC_VENDOR or 1;
SIO_RCVALL_MCAST                     = IOC_IN or IOC_VENDOR or 2;
SIO_RCVALL_IGMPMCAST                 = IOC_IN or IOC_VENDOR or 3;
SIO_KEEPALIVE_VALS                   = IOC_IN or IOC_VENDOR or 4;
SIO_ABSORB_RTRALERT                  = IOC_IN or IOC_VENDOR or 5;
SIO_UCAST_IF                         = IOC_IN or IOC_VENDOR or 6;
SIO_LIMIT_BROADCASTS                 = IOC_IN or IOC_VENDOR or 7;
SIO_INDEX_BIND                       = IOC_IN or IOC_VENDOR or 8;
SIO_INDEX_MCASTIF                    = IOC_IN or IOC_VENDOR or 9;
SIO_INDEX_ADD_MCAST                  = IOC_IN or IOC_VENDOR or 10;
SIO_INDEX_DEL_MCAST                  = IOC_IN or IOC_VENDOR or 11;

// Values for use with SIO_RCVALL* options
  RCVALL_OFF             = 0;
  RCVALL_ON              = 1;
  RCVALL_SOCKETLEVELONLY = 2;

implementation

end.


 
Verg ©   (2004-04-27 22:36) [18]

Вот, что получилось. Это, конечно, немного тяжеловато, но оптимизацию предлагаю сделать самим заинтересованным.
program Console;
{$APPTYPE CONSOLE}

{$DEFINE REALTIME}
{$DEFINE CHECKSUMM}

uses
 Windows,
 SysUtils,
 WinSock2 in "WinSock2.pas",
 mstcpip in "mstcpip.pas",
 IPUtils in "IPUtils.pas",
 IPHelper in "IPHelper.pas";

const
 MEGASIZE     = (1024*1024);

 MIN_SPEED_SIZE = 500;

var
 WSAData : TWSAData;
 Sa : TSockAddrIn;
 Rcvd : integer;
 RS   : TSocket;
 flag : DWORD;

 Buffer : array[0..IP_MAXPACKET-1] of byte;
 Iph : TIpHeader absolute Buffer;
 HeaderLen : DWORD;
 IPData    : pchar;

 DstIP   : DWORD;
 DstPort : WORD;
 Trafic0,
 Trafic: Int64;

 Tmv  : TTimeVal;
 StTime : DWORD;
 DGSpeedTimer, DGSpeedTimer2   : Int64;

 DGSpeedTimeSumm,
 DGSpeedCounter : Int64;

 FreqAvail : boolean;
 Freq : Int64;

 StartTime : TDateTime;

procedure SaveData;
var Fn : string;
   F  : text;
begin
 Fn := ExtractFilePath(ParamStr(0))+IntToStr(DstIp)+IntToStr(DstPort)+".dat";
 Assign(F, Fn);
 rewrite(F);
 WriteLn(F, StartTime, " ", Trafic);
 Close(F);
end;

procedure LoadData;
var Fn : string;
   F  : text;
begin
 Fn := ExtractFilePath(ParamStr(0))+IntToStr(DstIp)+IntToStr(DstPort)+".dat";
 Assign(F, Fn);
 if FileExists(Fn) then
 begin
   reset(F);
   ReadLn(F, StartTime, Trafic);
   Close(F);
 end else
 begin
   StartTime := now;
   Trafic := 0;
 end;
end;

function CheckIP( DstIP : DWORD ): boolean;
begin
 result := true;
 if (DstIp = htonl(INADDR_ANY)) or
    (DstIp = htonl(INADDR_LOOPBACK)) or
    (DstIp = htonl(INADDR_NONE)) then
   result := false;
end;

function CtrlHandler(dwCtrlType : DWORD):BOOL; stdcall;
var S : TSocket;
begin
 if RS<>INVALID_SOCKET then
 begin
   S:= RS;
   RS := INVALID_SOCKET;
   CloseSocket(S);
 end;
 result := BOOL(true);
end;

function ToOem(const S : string):string;
begin
 Result := S;
 if Result<>"" then
   CharToOemBuff(pchar(Result), pchar(Result), length(Result));
end;

function ProcessDGSpeed : double;
begin
 Result := -1;
 if not FreqAvail then
   exit;
 if DGSpeedCounter = 0 then
   DGSpeedCounter := 1;

 Result := ( DGSpeedCounter / (DGSpeedTimeSumm / Freq) ) / MEGASIZE;
 if DGSpeedCounter > 100*MEGASIZE then
 begin
   DGSpeedTimeSumm := 0;
   DGSpeedCounter := 0;
 end;
end;

function ProcessTrafic:boolean;
var MbSec : double;
begin
 Result := false;
 if Trafic0 > 0 then
 begin
   inc(Trafic, Trafic0);
   Trafic0 := 0;

   MbSec := Trafic/((Now - StartTime)*MEGASIZE);

   Write(ToOem("Трф. "+inet_ntoa(TInAddr(DstIP))+
                 " с порта "+IntToStr(ntohs(DstPort))+" = "),
            Trafic, #9,
            "(", MbSec:3:1, toOem(" МБ/сут)"));
   if FreqAvail then
     WriteLn(" ", ProcessDGSpeed:3:1, ToOem("МБ/с"))
   else
     WriteLn;
   SaveData;
   Result := true;
 end;
end;

procedure PrintErr(Err : DWORD; Wt : boolean);
begin
 Writeln(ToOem(SysErrorMessage(Err)));
 if Wt then ReadLn;
end;

procedure ExitErr;
begin
 if (WSAGetLastError<>NO_ERROR) and
    (WSAGetLastError<>WSAENOTSOCK) and
    (WSAGetLastError<>WSAEINTR) then
   PrintErr(WSAGetLastError, true)
 else
   if ProcessTrafic then
     ReadLn;
 if Rs<> INVALID_SOCKET then
   CloseSocket(RS);
 if WSAData.wVersion <> 0 then
   WSACleanup;
 halt(0);
end;

function checksocket(Ret : integer):integer;
begin
 Result := Ret;
 if Result = SOCKET_ERROR then
 begin
   if WSAGetLastError <> WSAETIMEDOUT then
    ExitErr
   else
    result :=0;
 end;
end;

function InterfaceTo( DstIp : DWORD; var IntIP : DWORD) : integer;
var Table : PMIB_IPADDRTABLE;
   TableSize : ulong;
   Bi : DWORD;
   I : integer;
   Res : DWORD;

   procedure CheckIPHLP(R: DWORD);
   begin
     if R<>NO_ERROR then
     begin
       WSASetLastError(R);
       ExitErr;
     end;
   end;

begin
 Result := -1;
 IntIp := INADDR_NONE;
 CheckIPHLP(GetBestInterface(DstIp, Bi) );
 TableSize := 0;
 Res := GetIpAddrTable(nil, TableSize, false);
 if TableSize <> 0 then
 begin
   GetMem(Table, TableSize);
   try
     CheckIPHLP(GetIpAddrTable(Table, TableSize, false));
     for I:= 0 to Table^.dwNumEntries-1 do
     if Table^.table[I].dwIndex = Bi then
     begin
       Result := 0;
       IntIP := Table^.table[I].dwAddr;
       if IntIP = htonl(INADDR_LOOPBACK) then
       begin
         // Получлось, что задан собственно один из адресов нашего хоста
         result := 1;
         IntIp := DstIP;
         Break;
       end;
       if  (IntIP and Table^.table[I].dwMask) =
           (DstIp and Table^.table[I].dwMask) then
       begin
         Result := 1;
         break;
       end;
     end;
   finally
     FreeMem(Table);
   end;
 end else
   CheckIPHLP(Res);
end;


 
Verg ©   (2004-04-27 22:37) [19]

procedure RealTime;
begin
 if not SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS) or
    not SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL) then
 begin
   WSASetLastError(GetLastError);
   ExitErr;
 end;
end;

function TCPInput(Iph: PIPHeader; TCPPacket : PTCPHeader; Size : word): boolean;
begin
 Result := false;
 if Size < sizeof(TTCPHeader) then exit;
 if DstPort<>0 then
   if TCPPacket^.Source <> DstPort then exit;      //Только нужный порт
 //SOCK_RAW гарантирует, что IP заголовок имеет правильную КС,
 // но на все остальные уровни он плевал, поэтому придется расчитать
 // КС TCP пакета самим
{$IFDEF CHECKSUMM}
 if net_chksum_add(PHCheckSumm(Iph^.src, Iph^.dst, IPPROTO_TCP, Size),
                   net_checksum(TCPPacket^, Size)
                  ) <> $FFFF then
   exit;
{$ENDIF}
 Inc(Trafic0, ntohs(Iph^.length));
 Result := true;
end;

begin
 Trafic  := 0;
 Trafic0 := 0;
 SetConsoleTitle("SOCK_RAW usage demo.");
 RS := INVALID_SOCKET;
 if ParamCount <> 2 then
 begin
   Writeln("Usage: "+ExtractFileName(ParamStr(0))+" <Target IP> <Target port>");
   Readln;
   Exit;
 end;

 DstIp := inet_addr(pchar(ParamStr(1)));
 if not CheckIP(DstIp) then
 begin
   Writeln("Invalid Target IP");
   Readln;
   Exit;
 end;
 DstPort := htons( StrToIntDef(ParamStr(2), 0) );

 if WSAStartup(MAKEWORD(2, 2), WSAData)<> NO_ERROR then
    ExitErr;
 try
   RS := socket(PF_INET, SOCK_RAW, IPPROTO_IP);
   if RS = INVALID_SOCKET then
     ExitErr;
   try
     ZeroMemory( @sa, sizeof(sa) );
     sa.sin_family := AF_INET;
     case InterfaceTo(DstIp, sa.sin_addr.S_addr) of
       -1 : ExitErr;
       0  : writeln(ToOem("Пакеты Target IP могут не приходить на наш хост."));
     end;
     checksocket(bind(RS, @sa, sizeof(sa)));
     Tmv.tv_sec  := 2;
     Tmv.tv_usec := 0;
     checksocket( setsockopt(RS, SOL_SOCKET, SO_RCVTIMEO,
                             pchar(@Tmv), sizeof(Tmv) ));
     flag:= 1;
     checksocket( ioctlsocket(RS, SIO_RCVALL , flag) );

     Tmv.tv_sec  := Tmv.tv_sec * 1000;
     SetconsoleCtrlHandler(@CtrlHandler, LongBool(TRUE));
     LoadData;
{$IFDEF REALTIME}
     RealTime;
{$ENDIF}

     StTime := GetTickCount;
     DGSpeedCounter := 0;
     FreqAvail :=QueryPerformanceFrequency(Freq);
     repeat
       if GetTickCount - StTime > DWORD(Tmv.tv_sec) then
         Rcvd := 0
       else
         Rcvd := checksocket( recv(RS, Buffer, sizeof(Buffer), 0) );
       if Rcvd > 0 then
       begin
         if FreqAvail then QueryPerformanceCounter( DGSpeedTimer );
         if Iph.dst.S_addr = DstIp then // Только нужный IP
         begin
           HeaderLen := (Iph.verlen and $F) shl 2;  // Длина IP заголовка
           IPData := pchar(@Iph)+HeaderLen;
           if Rcvd <> ntohs( Iph.length ) then
             WriteLn("Error: IP.LENGTH mismatch!");
           case Iph.protocol of
             IPPROTO_TCP : if TCPInput(@Iph,
                                       PTCPHeader( IPData ),
                                       DWORD(Rcvd) - HeaderLen) then
                              StTime := GetTickCount;
           end;
         end;
         if FreqAvail and (Rcvd > MIN_SPEED_SIZE) then
         begin
           QueryPerformanceCounter( DGSpeedTimer2 );
           Inc(DGSpeedTimeSumm, DGSpeedTimer2 - DGSpeedTimer);
           Inc(DgSpeedCounter, Rcvd);
         end;
       end else
       begin
         ProcessTrafic;
         StTime := GetTickCount;
       end;
     until false;
   finally
     closesocket(RS);
   end;
 finally
   WSACleanup;
 end;
end.


 
Rouse_ ©   (2004-04-27 23:05) [20]

> Digitman ©  
Сергей, большая просьба...
Я очень уважительно отношусь к Вашим знаниям и ни в коем случае не умаляю их, но большая просьба:
Пожалуйста, будьте более выдержанны к участникам форумов, я не могу пропускать посты с таким содержанием и приходится их удалять... :(
Я очень не хочу продолжать такую профилактику в будующем...


 
Verg ©   (2004-04-27 23:28) [21]

Ну вот, за приемлимое время у меня получилось:
Условия:
Win2K Pro RUS SP4 P4 1.5G 512M

За прошедшее с запуска время - потрябляемый моим адресом трафик через мой прокси - 20,6 МБ/сут. Средняя производительность счетчик в режиме REALTIME с расчетом конрольной суммы - 203 МБ/с.
Для сети  100 bps предельная производительность д.б ~12 МБ/c. Т.о. запас более чем достаточный.

Можно сделать NT-сервис с "предохранителем", например, чтобы верещала, если среднее потребление трафика превысило некоторый порог. Впрочем, наверняка это где-ниубдь, в каких-нибудь утилитах давно сделано :) в лучшем виде :))))


 
Digitman ©   (2004-04-28 08:01) [22]


> Rouse_ ©   (27.04.04 23:05) [20]


Ok.
Приношу извинения



Страницы: 1 вся ветка

Текущий архив: 2004.06.20;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.046 c
14-1086339695
Nick-From
2004-06-04 13:01
2004.06.20
Еду в командировку первый раз


8-1081227114
freeek
2004-04-06 08:51
2004.06.20
Нарисовать на картинке


14-1086268097
Vasya.ru
2004-06-03 17:08
2004.06.20
решение уравнений методом Гаусса


14-1085775071
Yorick
2004-05-29 00:11
2004.06.20
Существует ли любовь?


1-1086691251
zrv
2004-06-08 14:40
2004.06.20
Мастера подскажите по печати