Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > оцените пинговалку


Автор: _hunter 15.5.2008, 12:26
Добрый день.

Понадобилась мне пинговалка (плюсовая). Ррешил я портировать http://tangentsoft.net/wskfaq/examples/rawping.html проект. Но возникли у меня сомнения в правильности ее работы -- результаты отличаются от результатов виндового ping.exe.
Если кому-то не лень -- посмотрите что там не так.

С уважением...

P.S.
использование:
RawSocketsPing rawSocketPing("195.5.46.10", DEFAULT_PACKET_SIZE, DEFAULT_TTL);
rawSocketPing.Ping();

Автор: bel_nikita 15.5.2008, 18:21
К сожалению, посмотреть нет времени, но сейчас аккурат занимаюсь пингованием smile
Может что полезное найдешь.
Первый вариант "чисто под Винду", с использованием IcmpSendEcho:
Код

#include "stdafx.h"
#include <windows.h>
#include <winsock.h>
#include <Ipexport.h>
#include <icmpapi.h>

#include "GetErrorText.h"
#include "ping.h"

#pragma comment(lib,"comctl32")
#pragma comment(lib,"WSOCK32")
#pragma comment(lib,"IpHlpApi.lib")

typedef struct _stIP_STATUS{
  int code;
  const char* pText;
} stIP_STATUS;

stIP_STATUS ip_status[] = {
  {IP_BUF_TOO_SMALL,          "Buffer too small"  },
  {IP_DEST_NET_UNREACHABLE,   "Destination net unreachable"  },
  {IP_DEST_HOST_UNREACHABLE,  "Destination host unreachable"  },
  {IP_DEST_PROT_UNREACHABLE,  "Destination prot unreachable"  },
  {IP_DEST_PORT_UNREACHABLE,  "Destination port unreachable"  },
  {IP_NO_RESOURCES,           "No resources"  },
  {IP_BAD_OPTION,             "Bad options"  },
  {IP_HW_ERROR,               "HW error"  },
  {IP_PACKET_TOO_BIG,         "Packet too big"  },
  {IP_REQ_TIMED_OUT,          "Request time out"  },
  {IP_BAD_REQ,                "Bad request"  },
  {IP_BAD_ROUTE,              "Bad route"  },
  {IP_TTL_EXPIRED_TRANSIT,    "TTL expired transit"  },
  {IP_TTL_EXPIRED_REASSEM,    "TTL expired REASSEM"  },
  {IP_PARAM_PROBLEM,          "Parameters problem"  },
  {IP_SOURCE_QUENCH,          "Source quench"  },
  {IP_OPTION_TOO_BIG,         "Option too big"  },
  {IP_BAD_DESTINATION,        "Bad destination"  },
  {IP_ADDR_DELETED,           "Address deleted"  },
  {IP_DEVICE_DOES_NOT_EXIST,  "Device does not exist"  },
};

const char* GetPingError(int code)
{
  for (int i = 0; i < sizeof(ip_status)/sizeof(ip_status[0]); ++i )
  {
    if ( ip_status[i].code == code ) break;
  }
  if ( i >= sizeof(ip_status)/sizeof(ip_status[0]) )
    return "Unknown";
  return ip_status[i].pText;
}

//
// The next group are status codes passed up on status indications to
// transport layer protocols.
//
/*
#define              (IP_STATUS_BASE + 19)
#define IP_SPEC_MTU_CHANGE          (IP_STATUS_BASE + 20)
#define IP_MTU_CHANGE               (IP_STATUS_BASE + 21)
#define IP_UNLOAD                   (IP_STATUS_BASE + 22)
#define IP_ADDR_ADDED               (IP_STATUS_BASE + 23)
#define IP_MEDIA_CONNECT            (IP_STATUS_BASE + 24)
#define IP_MEDIA_DISCONNECT         (IP_STATUS_BASE + 25)
#define IP_BIND_ADAPTER             (IP_STATUS_BASE + 26)
#define IP_UNBIND_ADAPTER           (IP_STATUS_BASE + 27)

#define IP_DUPLICATE_ADDRESS        (IP_STATUS_BASE + 29)
#define IP_INTERFACE_METRIC_CHANGE  (IP_STATUS_BASE + 30)
#define IP_RECONFIG_SECFLTR         (IP_STATUS_BASE + 31)
#define IP_NEGOTIATING_IPSEC        (IP_STATUS_BASE + 32)
#define IP_INTERFACE_WOL_CAPABILITY_CHANGE  (IP_STATUS_BASE + 33)
#define IP_DUPLICATE_IPADD          (IP_STATUS_BASE + 34)
*/


class cping
{
public:
  cping()   { _hndlFile = IcmpCreateFile(); }
  ~cping()  { IcmpCloseHandle(_hndlFile); }
  DWORD
  IcmpSendEcho(
      IPAddr                   DestinationAddress,
      LPVOID                   RequestData,
      WORD                     RequestSize,
      PIP_OPTION_INFORMATION   RequestOptions,
      LPVOID                   ReplyBuffer,
      DWORD                    ReplySize,
      DWORD                    Timeout
      )
  {
    return ::IcmpSendEcho(_hndlFile,
                          DestinationAddress,
                          RequestData,
                          RequestSize,
                          RequestOptions,
                          ReplyBuffer,
                          ReplySize,
                          Timeout);
  }
protected:
private:
    HANDLE _hndlFile;                    // Handle for IcmpCreateFile()
};

int ping(const char* pIP, char* pResult, int size, int count)
{
    int x;
  int nRet;                            // General use return code
    ICMP_ECHO_REPLY icmpEcho;            // ICMP Echo reply buffer
    IP_OPTION_INFORMATION ipInfo;    // IP Options structure
  struct in_addr iaDest;        // Internet address structure
    DWORD dwRet;                          // DWORD return code
  FILE* memory;

  static cping  pingclass;
  //static cCriticalSection csLock;

  if ( !pIP || *pIP == 0 ) return 0;

  //csLock.lock();
  memory = fopen("nul", "w");
  ASSERT(memory);
  ASSERT(pResult);
  setvbuf(memory, pResult, _IOFBF, size);

  /*
  FILE file;
  // Create buffer for fprintf.
  file._flag = _IOREAD|_IOWRT|_IOSTRG|_IOMYBUF;
  file._ptr = file._base = (char*)buff;
  file._cnt = size;
  FILE* stream = &file;
  */

  // convert a string into a proper address for the IN_ADDR structure
  iaDest.s_addr = inet_addr(pIP);

  // Get an ICMP echo request handle        
    //hndlFile = IcmpCreateFile();

  /*
  if ( hndlFile == INVALID_HANDLE_VALUE )
  {
    LPTSTR pError = GetErrorText( 0x100UL );
    fwprintf(memory,pError);
    //csLock.unlock();
    return -1;
  }
  */

    for (x = 0; x < count; x++)
    {
    // Set some reasonable default values
        ipInfo.Ttl = 255;
        ipInfo.Tos = 0;
        ipInfo.Flags = 0;
        ipInfo.OptionsSize = 0;
        ipInfo.OptionsData = NULL;
        //icmpEcho.Options.Ttl = 256;

        // Request an ICMP echo
        dwRet = pingclass.IcmpSendEcho(iaDest.s_addr,                // Destination IP address
                                        NULL,                            // Pointer to buffer to send
                                        0,                                // Size of buffer in bytes
                                        &ipInfo,                      // Request options
                                        &icmpEcho,                    // Reply buffer
                                        sizeof(ICMP_ECHO_REPLY),
                                        1000/*5000*/);                  // Time to wait in milliseconds

        // Print the results
        iaDest.s_addr = icmpEcho.Address;

        fprintf(memory, "Reply from %s  Time=%ldms  TTL=%d",
                inet_ntoa(iaDest),
                icmpEcho.RoundTripTime,
                icmpEcho.Options.Ttl);

        if (icmpEcho.Status)
        {
            fwprintf(memory, _T(" Error: icmpEcho.Status=%ld"), icmpEcho.Status);
            break;
        }
    }
    //printf("\n");

  fclose(memory);

    // Close the echo request file handle
    //IcmpCloseHandle(hndlFile);

  nRet = !(x == count);
  //csLock.unlock();
  return nRet;
}


Добавлено через 6 минут и 35 секунд
Второй вариант, типо "кроссплатформенный пинг":
Все ненужное вырезать smile
См. прикрепленный файл

Автор: bel_nikita 15.5.2008, 18:38
А в добавок ко всему, есть проект ReactOS, где можно подсмотреть реализацию "виндового" ping.exe: http://www.reactos.org/generated/doxygen/d4/d6c/ping_8c-source.html

Автор: maaks_mouse 25.1.2009, 16:50
бел_никита, в "первом варианте" откуда взял Ipexport.h, icmpapi.h, GetErrorText.h, ping.h 
...у меня 6я студия если это важно ...file not found

З.Ы. спасибо за сцылку на ReactOS  smile 


...нашел в сети Ipexport.h и icmpapi.h, доьавил в проект
Ругается на :
icmpapi.h(24) : error C2146: syntax error : missing ';' before identifier 'IcmpCreateFile'

Код

...
#ifndef __WINE_ICMPAPI_H
#define __WINE_ICMPAPI_H

HANDLE STDCALL  IcmpCreateFile(
    VOID
    );
...

Автор: bel_nikita 25.1.2009, 23:10
maaks_mouse, 
тебе нужен http://msdn.microsoft.com/en-us/windows/bb980924.aspx?wt.svl=more_downloads

Автор: maaks_mouse 29.1.2009, 12:28
Аммм... пардон за не скромный вопрос... мне это нужно для winXP... полюзую еще 6-ю студию...
Я так понимаю, что для того чтобы ни в чем не испытывать нужды(что бы написать простенькую пинговалку, да и на будующее), мне нужно:
.NET Framework SDK v1.1 (потому что есть Supports .NET Framework 1.1 (нужно будет, когда начну учить дотНЭТ))
Windows Server 2003 R2 PSDK (потому что есть Visual Studio Compatibility с моей студией)
ну и 
Windows Server 2008 & .NET 3.5  SDK

...так? 

Автор: TIMUR777 24.5.2009, 19:02
http://forum.vingrad.ru/html/emoticons/pack/dash1.gif

Автор: andrew_121 24.5.2009, 22:26
TIMUR777, Ну и ЧТО ЭТО БЫЛО?!

Автор: TIMUR777 25.5.2009, 11:24
 а мне не можете подсказать как добавить время пингования каждого компа в этот пример smile 

Автор: jonie 25.5.2009, 21:40
TIMUR777 никак. Ваша программа не производит запросов ICMP и не соединяется с комьютерами (исключая локальный кеш DNS, ну и собственно DNS сервера).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)