Войти

Показать полную графическую версию : Мини ping


lehha
30-12-2005, 09:25
Всем привет!
Возникла следующая проблемка, необходимо отбросить "мертвые" IP адреса.
При проходе по подсети я коннектюсь к каждому айпишнику, но если в данный момент компьютер не включен то коннект проходит очень долго и изза этого тормозится весь процесс. Вопрос в том как мне реализовать этот мини пинг? Знаю что пинг использует ICMP протокол, но как мне правильно настроить сокет?? Кто с этим работал??
Вот кусочек моего кода проверки наличия компа в сети.

if (WSAStartup(0x0101, &wsadata)!=SOCKET_ERROR)
{
SOCKET s=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if (s!=INVALID_SOCKET)
{
sockaddr_in adrr;
int nTempTTL = 1; //TTL Какое должно быть
значение?? в чем оно измеряется в секундах или в мили секундах??
setsockopt(s, IPPROTO_IP, IP_TTL, (char*) &nTempTTL, sizeof(nTempTTL));
int nTempTOS = 1; //TOS - type-of-service, что это такое счем едет какие значения принимает??
setsockopt(s, IPPROTO_IP, IP_TOS, (char*) &nTempTOS, sizeof(nTempTTL));
unsigned int ip = inet_addr(FullAddress);
phe = gethostbyaddr((char*)&ip,4,AF_INET );
adrr.sin_addr.S_un.S_addr=((struct in_addr *)phe->h_addr_list[0])->s_addr;
char buff[100];
adrr.sin_family = AF_INET;
sendto(s, buff, sizeof(buff), 0, (sockaddr*)&addr, sizeof(addr))
re = WSAGetLastError();
}
}

И так вопросов сразу оч много
TTL Какое должно быть значение?? в чем оно измеряется в секундах или в мили секундах??
TOS - type-of-service, что это такое счем едет какие значения принимает??
На какой порт отсылать информацию, что должен содержать buff.
Спасибо за рание.

lehha
13-01-2006, 08:29
Всем спасибо разобрался, если интересует могу отпостить год.

hasherfrog
14-01-2006, 00:44
lehha
Интересно было бы глянуть. Я в своё время отказался от ICMP (линукс потому что нужен был обязательно), сделал на TCP обычном. Ибыл там у меня запар один... В общем, пишите :) Ещё кому-нибудь пригодится...

lehha
16-01-2006, 08:42
#pragma once
#include "Ping.h"

inline USHORT checksum(USHORT *buffer, int size) {
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size )
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}

inline BOOL decode_resp(char *buf, int bytes,struct sockaddr_in *from)
{
IpHeader *iphdr;
IcmpHeader *icmphdr;
unsigned short iphdrlen;
iphdr = (IpHeader *)buf;
iphdrlen = iphdr->h_len * 4 ;
if (bytes < iphdrlen + ICMP_MIN)
return TRUE;
icmphdr = (IcmpHeader*)(buf + iphdrlen);
if (icmphdr->i_type != ICMP_ECHOREPLY)
return FALSE;
if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
return FALSE;
return TRUE;
}
BOOL Ping(char* host)
{
WSADATA WSAData;
SOCKET sockRaw;
if (WSAStartup(MAKEWORD(2,1),&WSAData)!= 0)
return FALSE;
sockRaw = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,0);
if (sockRaw==INVALID_SOCKET)
return FALSE;
int timeout = 1, bread;
bread = setsockopt (sockRaw, IPPROTO_IP , IP_TTL, (char*)&timeout, sizeof(timeout));
if (bread == SOCKET_ERROR)
{
closesocket(sockRaw);
WSACleanup( );
return FALSE;
}
timeout = 1;
bread = setsockopt(sockRaw, IPPROTO_IP , IP_TTL, (char*)&timeout, sizeof(timeout));
if(bread == SOCKET_ERROR)
{
closesocket(sockRaw);
WSACleanup( );
return FALSE;
}
SOCKADDR_IN dest_sin, from_sin;
memset(&dest_sin,0,sizeof(dest_sin));
dest_sin.sin_addr.s_addr = inet_addr((char*)host);
dest_sin.sin_family = AF_INET;
char *icmp_data = new char[MAX_PACKET];
memset(icmp_data,0,MAX_PACKET);
IcmpHeader *icmp_hdr;
char *datapart;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->i_type = ICMP_ECHO;
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum = 0;
datapart = icmp_data + sizeof(IcmpHeader);
int datasize;
datasize = DEF_PACKET_SIZE;
memset(datapart,'E', datasize - sizeof(IcmpHeader));
char *recvbuf;
recvbuf = (char*)malloc(MAX_PACKET);
int iRecvLen;
iRecvLen = sizeof (from_sin);
int bwrote;
((IcmpHeader*)icmp_data)->i_cksum = 0;
((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);
bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest_sin, sizeof(dest_sin));
if (bwrote == SOCKET_ERROR)
{
delete icmp_data;
closesocket(sockRaw);
WSACleanup( );
return FALSE;
}
bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from_sin, &iRecvLen);
if (bread == SOCKET_ERROR)
{
delete icmp_data;
closesocket(sockRaw);
WSACleanup( );
return FALSE;
}
if (decode_resp(recvbuf,bread,&from_sin)==TRUE)
{
delete icmp_data;
closesocket(sockRaw);
WSACleanup( );
return TRUE;
}
delete icmp_data;
closesocket(sockRaw);
WSACleanup( );
return FALSE;
}

Если Ping переделать в main() то в принципе рабочая программа, возвращаяет TRUE если пинг прошел.

а вот и хидер

#pragma once
#include "Winsock2.h"
#include "WS2TCPIP.H"

#pragma comment( lib, "Ws2_32.lib" )

#define ICMP_MIN 8
#define DEF_PACKET_SIZE 32
#define MAX_PACKET 1024
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

typedef struct iphdr {
unsigned int h_len:4;
unsigned int version:4;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
} IpHeader;

typedef struct _ihdr {
BYTE i_type;
BYTE i_code;
USHORT i_cksum;
USHORT i_id;
ULONG timestamp;
} IcmpHeader;
inline USHORT checksum(USHORT *buffer, int size);
inline BOOL decode_resp(char *buf, int bytes,struct sockaddr_in *from);
BOOL Ping(char* host);

Вообще мне было необходимо проверить наличие компьютера в сети т.е. если от него пришел обратный пакет, то он присутствует, при небольшой доработке можно сделать полноценный пинг.




© OSzone.net 2001-2012