
Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа 2 / Timestamp / Timestamp
.cpp//Пример реализации утилиты для запроса временной метки
#include "stdafx.h"
#include <math.h>
#define ICMP_ECHO ((USHORT)13) // код сообщения ICMP_ECHO
#define ICMP_MAXBUF ((DWORD)0x1000) // максимальный размер пакета ICMP
#define ICMP_DATA ((DWORD)32) // размер данных ICMP
#define ICMP_TIMEOUT ((DWORD)1000) // интервал
// макрос для инициализации структур
#define constructor() {ZeroMemory(this,sizeof(*this));}
// структура заголовка пакета IP
typedef struct taglP_HEADER
{
taglP_HEADER() constructor();
unsigned char h_len:4; // длиназаголовка
unsigned char version :4; // версия протокола
unsigned char tos; // тип сервиса
unsigned short totalJen; // общая длина пакета
unsigned short ident; // идентификатор пакета
unsigned short frag_and_flags; // флаги
unsigned char ttl ; // значение TTL
unsigned char proto; // код протокола
unsigned short checksum; // контрольная сумма
unsigned int sourcelP; // исходный адрес
unsigned int destlP; // конечный адрес
} IP_HEADER,*PIP_HEADER;
// структура заголовка пакета ICMP
typedef struct tagICMP_MSG
{
tagICMP_MSG() {constructor();}
BYTE i_type; // тип сообщения
BYTE i_code; // расширенный код сообщения
USHORT i_cksum; // контрольная сумма
USHORT i_id; // идентификаторприложения
USHORT i_seq; // номер в последовательности
// это поле не входит в заголовок пакета и будет
// находиться в области дополнительных данных
DWORD timestamp; // временная метка
DWORD timestamp_in; // временная метка на входе
DWORD timestamp_out; // временная метка на выходе
} ICMP_MSG, *PICMP_MSG;
USHORT g_appid;
// функция: _sc
// назначение: вывод на экран кода ошибки WinSock и
// завершение работы
bool _sc(int wsacode, const char *msg=0)
{
bool ret=false;
if (wsacode==SOCKET_ERROR)
{
printf ("wsaerror=%d,%s\n ",WSAGetLastError(),(msg)?(msg):(""));
ret=true;
}
return ret;
}
// функция: checksum
// назначение: вычисление контрольной суммы
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);
}
//функция: icmp_parse
// назначение: разбор полученных пакетов
bool icmp_parse(IP_HEADER *iph, ICMP_MSG *icmph, sockaddr_in *from, int len)
{
/*if(icmph->i_id=g_appid)
{
printf("(:\n");
return false;
} */
SYSTEMTIME SysTime;
GetLocalTime(&SysTime);
printf("Reply from %s TTL=%d \nlocal_time =%d:%d:%d.%d ms.\nserver_time_in =%d:%d:%d.%d ms. \nserver_time_out=%d:%d:%d.%d ms.\nserver_tmestamp=%d\n\n",
inet_ntoa(from->sin_addr),iph->ttl,
SysTime.wHour, SysTime.wMinute, SysTime.wSecond, SysTime.wMilliseconds,
/*GetTickCount()-icmph->timestamp,*/
icmph->timestamp_in/(60*60*1000),(icmph->timestamp_in%(60*60*1000))/60/1000,(icmph->timestamp_in%(60*1000))/1000,(icmph->timestamp_in%(1000)),
icmph->timestamp_out/(60*60*1000),(icmph->timestamp_out%(60*60*1000))/60/1000,(icmph->timestamp_out%(60*1000))/1000,(icmph->timestamp_out%(1000)),
icmph->timestamp_out);
return true;
}
//sprintf (szCurrTime, "Current time = %lu Tick count = %lu",dwCurrTime, dwTickCount);
// функция: echo
// назначение: цикл посылки/принятия сообщений
void echo(const char *hostname)
{
hostent *he;
SOCKET sock;
WSADATA wsad;
sockaddr_in dest;
unsigned size;
char buf[ICMP_MAXBUF];
PIP_HEADER iph=(PIP_HEADER)buf;
// инициализация библиотеки WinSock
if(_sc(WSAStartup(MAKEWORD(2,1),&wsad))) ExitProcess(-1);
// создание сокета ICMP
sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,0,0,0);
printf("Pinging host \\\\%s\n",hostname);
// получение адреса хоста no его имени
if ((he=gethostbyname(hostname))==0)
{
_sc(SOCKET_ERROR);
ExitProcess(-1);
}
ZeroMemory(&dest,sizeof(dest));
CopyMemory(&(dest.sin_addr),he->h_addr,he->h_length);
dest.sin_family=he->h_addrtype;
printf("Host IP %s\n",inet_ntoa(dest.sin_addr));
for (;;) //цикл посылки/принятия сообщений
{
ICMP_MSG data_out;
int len=sizeof(dest);
size=sizeof(ICMP_MSG)+ICMP_DATA; // общий размер пакета
// заполнение поля необязательных данных пакета
memset((char*)(buf+sizeof(ICMP_MSG)),'#',ICMP_DATA);
// заполнение заголовка пакета
data_out.timestamp=GetTickCount(); // время отправления
data_out.timestamp_in=0;
data_out.timestamp_out=0;
data_out.i_type=ICMP_ECHO; // тип
data_out.i_id=g_appid; // хэндл приложения
data_out.i_cksum=checksum((USHORT*)&data_out,size); // контрольная сумма
// отправка пакета с запросом ICMP_ECHO
_sc(sendto(sock,(char*)&data_out,size,0,(sockaddr*)&dest,sizeof(dest))); // получение ответа и разбор пакета
do _sc(recvfrom(sock,buf,ICMP_MAXBUF,0,(sockaddr*)&dest,&len));
while(!icmp_parse((IP_HEADER*)buf,(ICMP_MSG*)(buf+iph->h_len*4),&dest,ICMP_DATA));
// пауза между посылаемыми пакетами
Sleep(ICMP_TIMEOUT);
}
}
// функция: main
// назначение: точка входа в приложение
int main(int argc, char* argv[])
{
// если нет параметров командной строки, то вывод информации
if(argc!=2)
{
printf("Usage: ping.exe [hostname]\n");
}
else
{
g_appid=(USHORT)GetCurrentProcessId();
echo(argv[1]);
}
return 0;
}
Соседние файлы в папке Timestamp