Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Мини ping (http://forum.oszone.net/showthread.php?t=58781)

lehha 30-12-2005 09:25 388063

Мини ping
 
Всем привет!
Возникла следующая проблемка, необходимо отбросить "мертвые" 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 391804

Всем спасибо разобрался, если интересует могу отпостить год.

hasherfrog 14-01-2006 00:44 392167

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

lehha 16-01-2006 08:42 392944

Код:

#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);

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


Время: 21:33.

Время: 21:33.
© OSzone.net 2001-