Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Socket Windows recvfrom не принимает данные, visual studio 2010, recvfrom, select 
V
    Опции темы
wondertalik
Дата 17.5.2012, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Портирую код tracerudp с линукс под виндоус. По сути это упрощенная утилита traceroute. Создаются два сокета, один для отправки udp пакета, второй для получения icmp. Пакет отправляется на указанный узел, узел отвечает icmp сообщением. А принять это сообщение не могу. recvfrom в packet_ok возвращает -1. Где моя ошибка. Кто может подсказать? Использую visual studio 2010.
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <process.h>
#include <time.h>
#include <windows.h>

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

#define BUFSIZE 1500
#define ICMP_TIMXCEED    11
#define ICMP_TIMXCEED_INTRANS 0
#define ICMP_UNREACH    3
#define ICMP_UNREACH_PORT    3

typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;

/* стуктура даних UDP */
struct outdata {             
  int outdata_seq;           /* порядковий номер */
  int outdata_ttl;           /* значення TTL */
  struct _SYSTEMTIME outdata_tv; /* час відправлення пакета */
};

struct iphdr {
    u_int32_t ihl:4;
    u_int32_t version:4;
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
};

struct icmp
{
  u_int8_t  icmp_type;    /* type of message, see below */
  u_int8_t  icmp_code;    /* type sub code */
  u_int16_t icmp_cksum;    /* ones complement checksum of struct */
  union
  {
    struct ih_idseq        /* echo datagram */
    {
      u_int16_t icd_id;
      u_int16_t icd_seq;
    } ih_idseq;
  } icmp_hun;
#define    icmp_id        icmp_hun.ih_idseq.icd_id
#define    icmp_seq    icmp_hun.ih_idseq.icd_seq
  union
  {
    u_int8_t    id_data[1];
  } icmp_dun;
#define    icmp_data    icmp_dun.id_data
};


char recvbuf[BUFSIZE];
char sendbuf[BUFSIZE];

SOCKET sendfd =  INVALID_SOCKET; /* дескриптор сокета для отправки UDP-дейтаграмм */
SOCKET recvfd =  INVALID_SOCKET; /* дескриптор сырого сокета для приема ICMP-сообщений */
struct sockaddr_in sasend;
 /* структура sockaddr() для отправки пакета */
struct sockaddr_in sabind;
 /* структура sockaddr() для связывания порта отправителя */
struct sockaddr_in sarecv;
 /* структура sockaddr() для получения пакета */
struct sockaddr_in salast;
 /* последняя структура sockaddr() для получения */
int sport;
int dport;

int ttl;
int probe;
int max_ttl = 1;
 /* максимальное значение поля TTL */
int nprobes = 1;
  /* количество пробных пакетов */
int dport = 32768 + 666;
 /* начальный порт получателя */
int datalen = sizeof(struct outdata);
 /* длина поля данных UDP */

WSADATA wsaData;

int main(int argc, char **argv) {

    int iResult;
    int seq = 0;
    int code = 0;
    int done = 0;
    double rtt = 0.0;
    struct hostent *hp = NULL;
    struct outdata *outdata = NULL;
    struct _SYSTEMTIME tvrecv;
    
    //ініціюємо сокет
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
    printf("WSAStartup failed: %d\n", iResult);
    return 1;
    }

    if (argc != 2) {
    fprintf(stderr, "Usage: %s <hostname>\n", argv[0]);
    exit(-1);
  }

  if ( (hp = gethostbyname(argv[1])) == NULL) {
    printf("gethostbyname() failed");
    exit(-1);
  }

  if ( (recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
    printf("socket() failed");
    WSACleanup();
    exit(-1);
  }

   if ( (sendfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    printf("socket() failed");
    WSACleanup();
    exit(-1);
  }

  sport = (_getpid() & 0xffff) | 0x8000;
 /* номер порта UDP отправителя */

  ZeroMemory(&sasend, sizeof(sasend));
  sasend.sin_family = AF_INET;
  sasend.sin_addr= *((struct in_addr *) hp->h_addr);

  sabind.sin_family = AF_INET;
  sabind.sin_port = htons(sport);
  if (bind(sendfd, (struct sockaddr *)&sabind, sizeof(sabind)) != 0)
    printf("bind() failed");

   for (ttl = 1; ttl <= max_ttl && done == 0; ttl++) {
    iResult = setsockopt(sendfd, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));
    ZeroMemory(&salast, sizeof(salast));

    //printf("%2d  ", ttl);
    fflush(stdout);

     for (probe = 0; probe < nprobes; probe++) {
      outdata = (struct outdata *)sendbuf;
      outdata->outdata_seq = ++seq;
      outdata->outdata_ttl = ttl;
      
      GetSystemTime(&outdata->outdata_tv);
      sasend.sin_port = htons(dport + seq);

      if (sendto(sendfd, sendbuf, datalen, 0, (struct sockaddr *)&sasend, sizeof(sasend)) < 0) {
        printf("sendto() failed");
        WSACleanup();
        exit(-1);
      }

     packet_ok(seq, &tvrecv);
     }
   }
}

int packet_ok(int seq, struct _SYSTEMTIME *tv) {
  int n;
  int len;

  fd_set fds;
  struct timeval wait;

  wait.tv_sec = 4;
 /* ждать ответа не более 4-х секундВ*/
  wait.tv_usec = 0;

   for (;;) {
    len = sizeof(sarecv);

    FD_ZERO(&fds);
    FD_SET(recvfd, &fds);
    if ((n = select(0, &fds, NULL, NULL, &wait) == SOCKET_ERROR)) {
        printf("select failed with error %d\n", WSAGetLastError());
        return -3;
    } else {
        n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len);
        printf("%d\n", n);

    }
      
   }
   return -1;
}

PM MAIL   Вверх
feodorv
Дата 17.5.2012, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45




M
feodorv
Тема перемещена из раздела C/C++: Системное программирование и WinAPI


Добавлено @ 17:34
Цитата(wondertalik @  17.5.2012,  17:13 Найти цитируемый пост)
recvfrom в packet_ok возвращает -1. Где моя ошибка.

WSAGetLastError вызывали?
Отправка/получение данных по сырым сокетам в Виндах возможна только из под администратора. И то говорят, что в седьмых виндах и это зарубили (сам я не пробовал)...

Это сообщение отредактировал(а) feodorv - 17.5.2012, 17:34


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 17.5.2012, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Код

    if ((n = select(0, &fds, NULL, NULL, &wait) == SOCKET_ERROR)) {
        printf("select failed with error %d\n", WSAGetLastError());
        return -3;
    } else {
        recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len);
        printf("%d\n", WSAGetLastError());
        return -2;
    }

возвращает -2, код 10022(WSAEINVAL) - http://msdn.microsoft.com/en-us/library/wi...0(v=vs.85).aspx

Это сообщение отредактировал(а) wondertalik - 17.5.2012, 21:07
PM MAIL   Вверх
feodorv
Дата 17.5.2012, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  17.5.2012,  19:55 Найти цитируемый пост)
возвращает -2

-1???


Цитата(wondertalik @  17.5.2012,  19:55 Найти цитируемый пост)
 код 10022(WSAEINVAL)

Не знаю точно, в чём тут дело, но, судя по всему, не нравится сокет. Сокет нужно править с помощью WSAIoctl( ... SIO_RCVALL ... ) (что не так просто, так как требует привязки сырого сокета к интерфейсу).

Кроме того, в приведённом коде select проверяется на возвращаемое значение SOCKET_ERROR, а на 0 не проверяется (для существующего кода без правки сокета select всегда будет возвращать 0 - ICMP пакетов нет)))).


BSD-сокеты хороши в Юниксе, в Виндах лучше пользоваться родным WinSock API  и неблокируемыми сокетами. И вот это работает:
Код

SOCKET rawsc = INVALID_SOCKET;
WSAEVENT rawscEvent = WSA_INVALID_EVENT;

if( (rawsc = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP)) == INVALID_SOCKET )
{
  ...
}
else if( (rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT )
{
  ...
}
else if( WSAEventSelect( rawsc, rawscEvent, FD_READ) == SOCKET_ERROR )
{
  ...
}

...
events[count++] = rawscEvent;
rv = WSAWaitForMultipleEvents( count, events, FALSE, 60000, FALSE);
...
bytes = recvfrom( ds, data, DATA_SIZE, 0, (struct sockaddr *) &sockAddr, &len);
...



Это сообщение отредактировал(а) feodorv - 17.5.2012, 23:33


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 17.5.2012, 23:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Может я чего-то не понимаю?
Код

 if ( (recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == SOCKET_ERROR) {
    printf("socket() failed, %d\n", WSAGetLastError());
    WSACleanup();
    exit(-1);
  }


Код

int packet_ok(int seq) {
  int n;
  int len;
  int count=1;
  WSAEVENT rawscEvent = WSA_INVALID_EVENT;
  WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];

  for(;;) {
      len = sizeof(sarecv);
  if((rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT) {
      printf("WSACreateEvent failed %d\n", WSAGetLastError());
      return -1;
  } else if(WSAEventSelect(recvfd, rawscEvent, FD_READ) == SOCKET_ERROR) {
       printf("WSAEventSelect failed %d\n", WSAGetLastError());
      return -1;
  }
  events[count++] = rawscEvent;
  
  if((WSAWaitForMultipleEvents( count, events, FALSE, 40000, FALSE)) == WSA_WAIT_TIMEOUT) {
      printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError());
  } else {
  n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len);
  printf("n = %d", n);
  break;
  }
  }
  return 0;
}


recvfrom возвращает -1 (n).

Это сообщение отредактировал(а) wondertalik - 17.5.2012, 23:55
PM MAIL   Вверх
feodorv
Дата 18.5.2012, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  18.5.2012,  00:47 Найти цитируемый пост)
  int count=1;

Начинаем с 0...

Добавлено @ 00:15
Цитата(wondertalik @  18.5.2012,  00:47 Найти цитируемый пост)
for(;;) {
     ...
  if((rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT) {
      printf("WSACreateEvent failed %d\n", WSAGetLastError());
      return -1;
  } else if(WSAEventSelect(recvfd, rawscEvent, FD_READ) == SOCKET_ERROR) {
       printf("WSAEventSelect failed %d\n", WSAGetLastError());
      return -1;
  }
  events[count++] = rawscEvent;

Это всё до фора нужно делать...

Добавлено через 5 минут
И даже вне packet_ok...

Добавлено через 7 минут и 53 секунды
Цитата(wondertalik @  18.5.2012,  00:47 Найти цитируемый пост)
  if((WSAWaitForMultipleEvents( count, events, FALSE, 40000, FALSE)) == WSA_WAIT_TIMEOUT) {

Поскольку событие одно, то можно просто
Код

if((WSAWaitForMultipleEvents( 1, &rawscEvent, FALSE, 40000, FALSE)) != WSA_WAIT_EVENT_0) 


Это сообщение отредактировал(а) feodorv - 18.5.2012, 00:15


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 18.5.2012, 01:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Код

int packet_ok(int seq) {
  int n;
  int len;
  int count=0, iResult = 0;
  WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
  DWORD rv = 2;
  BOOL bResult = FALSE;

  len = sizeof(sarecv);
  
  events[count++] = rawscEvent;
  while(1) {
if((rv = WSAWaitForMultipleEvents(1, &rawscEvent, FALSE, 1000, FALSE)) != WSA_WAIT_EVENT_0) {
      printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError());
  }
  bResult = WSAResetEvent(rawscEvent);
  if (bResult == FALSE) {
            wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
        }
  if((n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len))==SOCKET_ERROR) {
           iResult = WSAGetLastError();
        if (iResult != WSA_IO_PENDING)
            wprintf(L"recvfrom failed with error = %d\n", iResult);
    }
  }
  return -1;
}

Таймаут 1с. В течении 2 сек возвращается :
Код

WSAWaitForMultipleEvents failed 0
recvfrom failed with error = 10022
WSAWaitForMultipleEvents failed 10022
recvfrom failed with error = 10022

Где же подвох?

Уже смотрел и сюда: http://msdn.microsoft.com/en-us/library/wi...9(v=vs.85).aspx

Код

  WSAEVENT rawscEvent = WSA_INVALID_EVENT;

  if((rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT) {
      printf("WSACreateEvent failed %d\n", WSAGetLastError());
      return -1;
  }


  if(WSAEventSelect(recvfd, rawscEvent, FD_READ) == SOCKET_ERROR) {
       printf("WSAEventSelect failed %d\n", WSAGetLastError());
      return -1;
  }


вынес в main.

Это сообщение отредактировал(а) wondertalik - 18.5.2012, 01:42
PM MAIL   Вверх
feodorv
Дата 18.5.2012, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  18.5.2012,  02:22 Найти цитируемый пост)
3: WSAWaitForMultipleEvents failed 10022

WSAWaitForMultipleEvents просто завершается с WSA_WAIT_TIMEOUT (код ошибки при этом наследуется, то есть не правится).

Лучше так:
Код
rv = WSAWaitForMultipleEvents(1, &rawscEvent, FALSE, 1000, FALSE);
switch( rv )
{
  case WSA_WAIT_EVENT_0:
    ...
    ... recvfrom ...
    ...
  case WSA_WAIT_TIMEOUT:
    ...
  default:
    ...
}


Цитата(wondertalik @  18.5.2012,  02:22 Найти цитируемый пост)
Где же подвох?

Вот не знаю smile Пока по сокету что-нибудь не пошлёшь, он как будто запечатанный. Стоит что-то послать, и он начинает ловить ICMP...

Код

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

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

SOCKET rawsc = INVALID_SOCKET;
WSAEVENT rawscEvent = WSA_INVALID_EVENT;

static BOOL inetStartup( void )
{
  WORD wVersionRequested;
  WSADATA wsaData;

  wVersionRequested = MAKEWORD( 2, 2);
  if( WSAStartup( wVersionRequested, &wsaData) != 0 )
  {
    printf( "Couldn't find a WinSock DLL\n" );
    return FALSE;
  }

  if( (LOBYTE( wsaData.wVersion ) < 1 ||
      (LOBYTE( wsaData.wVersion ) == 1 && HIBYTE( wsaData.wVersion ) < 1)) )
  {
    printf( "Couldn't find a usable WinSock DLL\n" );
    return FALSE;
  }

  return TRUE;
}

static void inetCloseup( void )
{
  WSACleanup();
}

static BOOL socketOpen( void )
{
  int ttl = 255;

  if( (rawsc = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP)) == INVALID_SOCKET )
  {
    printf( "Can't open ICMP socket, error code %u", WSAGetLastError());
    return FALSE;
  }
  else if( (rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT )
  {
    printf( "Can't create ICMP socket event, error code %u", WSAGetLastError());
    return FALSE;
  }
  else if( WSAEventSelect( rawsc, rawscEvent, FD_READ) == SOCKET_ERROR )
  {
    printf( "Can't bind ICMP socket and event together, error code %u", WSAGetLastError());
    return FALSE;
  }

  if( setsockopt( rawsc, IPPROTO_IP, IP_TTL, (char *) &ttl, sizeof(ttl)) != 0 )
    printf( "Can't set socket option IP_TTL, error code %u", WSAGetLastError());

  return TRUE;
}

static void socketClose( void )
{
  if( rawsc != INVALID_SOCKET ) closesocket( rawsc );
  rawsc = INVALID_SOCKET;
  if( rawscEvent != WSA_INVALID_EVENT ) WSACloseEvent( rawscEvent );
  rawscEvent = WSA_INVALID_EVENT;
}

static unsigned short checksum( unsigned short *buffer, int size)
{
  unsigned long cksum = 0;

  while( size > 1 )
  {
    cksum += *buffer++;
    size -= sizeof(unsigned short);
  }

  if( size != 0 ) cksum += *(unsigned char *) buffer;

  cksum = (cksum >> 16) + (cksum & 0xffff);
  cksum += (cksum >>16);
  return (unsigned short) (~cksum);
}

typedef struct _ihdr
{
  BYTE i_type;
  BYTE i_code;
  USHORT i_cksum;
  USHORT i_id;
  USHORT i_seq;
  DWORD timestamp;
} IcmpHeader;

#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

static void socketSend( void )
{
  struct sockaddr_in sockAddr;
  unsigned char data[128];
  IcmpHeader *icmpHdr = (IcmpHeader *) data;

  ZeroMemory( &sockAddr, sizeof(sockAddr));
  sockAddr.sin_family = AF_INET;
  sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );

  ZeroMemory( data, sizeof(data));
  icmpHdr->i_type = ICMP_ECHO;
  icmpHdr->i_code = 0;
  icmpHdr->i_id = (USHORT) GetCurrentProcessId();
  icmpHdr->i_seq = 0;
  icmpHdr->i_cksum = 0;
  icmpHdr->timestamp = GetTickCount();
  memset( &data[sizeof(IcmpHeader)],'X', sizeof(data)-sizeof(IcmpHeader));
  icmpHdr->i_cksum = checksum( (unsigned short *) data, sizeof(data));

  if( sendto( rawsc, data, sizeof(data), 0, (struct sockaddr *) &sockAddr,
        sizeof(sockAddr)) == SOCKET_ERROR )
    printf( "Error of sendto, error code %u\n", WSAGetLastError());
}

static void socketRead( void )
{
  BOOL success = TRUE;

  do
  {
    WSANETWORKEVENTS info;
    DWORD rv = WSAWaitForMultipleEvents( 1, &rawscEvent, FALSE, 60000, FALSE);

    switch( rv )
    {
      case WSA_WAIT_EVENT_0:
        printf( "WSA_WAIT_EVENT_0\n" );
        if( WSAEnumNetworkEvents( rawsc, rawscEvent, &info) == SOCKET_ERROR )
        {
          WSAResetEvent( rawscEvent );
          printf( "Can't enum network events for ICMP socket, error code %u", WSAGetLastError());
        }
        else if( (info.lNetworkEvents & FD_READ) != 0 )
        {
          struct sockaddr_in sockAddr;
          unsigned char data[512];
          int len = sizeof( sockAddr );
          int bytes = recvfrom( rawsc, data, sizeof(data), 0,
                (struct sockaddr *) &sockAddr, &len);
          printf( "Has ICMP packet, %d bytes\n", bytes);
        }
        break;
      case WSA_WAIT_TIMEOUT:
        printf( "WSA_WAIT_TIMEOUT\n" );
        success = FALSE;
        break;
      default:
        printf( "WSAEnumNetworkEvents error %u\n", WSAGetLastError());
        success = FALSE;
        break;
    }
  } while( success );
}

void main( void )
{
  if( !inetStartup() ) return;

  if( socketOpen() )
  {
    socketSend();
    socketRead();
  }
  socketClose();

  inetCloseup();
}


Это сообщение отредактировал(а) feodorv - 16.9.2013, 04:39


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 18.5.2012, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Код

rv = WSAWaitForMultipleEvents(1, &rawscEvent, FALSE, 1000, FALSE);

А почему первый параметр 1, а не сокет rawsc?
PM MAIL   Вверх
feodorv
Дата 18.5.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  18.5.2012,  15:53 Найти цитируемый пост)
А почему первый параметр 1, а не сокет rawsc? 

Потому что первый параметр - число событий, которых мы ожидаем. В явном виде сокета здесь нет, но есть событие, ассоциированное с сокетом  smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 18.5.2012, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Я благодарен Вам за помощь. Очень помогаете. Надеюсь и дальше сможете мне помочь, дабы добить до конца тему. И так, благодаря ВАм, пакеты icmp успешно принимаются. Вот код который получился на данный момент:
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <process.h>
#include <time.h>
#include <windows.h>

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

#define BUFSIZE 1500
#define ICMP_TIMXCEED    11
#define ICMP_TIMXCEED_INTRANS 0
#define ICMP_UNREACH    3
#define ICMP_UNREACH_PORT    3
#define ICMP_ECHO 8

typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;

/* стуктура даних UDP */
struct outdata {             
    int outdata_seq;           /* порядковий номер */
    int outdata_ttl;           /* значення TTL */
    DWORD timestamp; /* час відправлення пакета */
};

struct udphdr {
    u_short    uh_sport;        /* source port */
    u_short    uh_dport;        /* destination port */
    u_short    uh_ulen;        /* udp length */
    u_short    uh_sum;            /* udp checksum */
};

struct iphdr {
    u_int32_t ihl:4;
    u_int32_t version:4;
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
};

struct icmp
{
    u_int8_t  icmp_type;    /* type of message, see below */
    u_int8_t  icmp_code;    /* type sub code */
    u_int16_t icmp_cksum;    /* ones complement checksum of struct */
    union
    {
        struct ih_idseq        /* echo datagram */
        {
            u_int16_t icd_id;
            u_int16_t icd_seq;
        } ih_idseq;
    } icmp_hun;
#define    icmp_id        icmp_hun.ih_idseq.icd_id
#define    icmp_seq    icmp_hun.ih_idseq.icd_seq
    union
    {
        u_int8_t    id_data[1];
    } icmp_dun;
#define    icmp_data    icmp_dun.id_data
};


char recvbuf[BUFSIZE];
char sendbuf[BUFSIZE];

SOCKET sendfd =  INVALID_SOCKET; /* дескриптор сокета для отправки UDP-дейтаграмм */
SOCKET recvfd =  INVALID_SOCKET; /* дескриптор сырого сокета для приема ICMP-сообщений */
struct sockaddr_in sasend;
/* структура sockaddr() для отправки пакета */
struct sockaddr_in sabind;
/* структура sockaddr() для связывания порта отправителя */
struct sockaddr_in sarecv;
/* структура sockaddr() для получения пакета */
struct sockaddr_in salast;
/* последняя структура sockaddr() для получения */
int sport;
int dport;
int n = 0;

int ttl;
int probe;
int max_ttl = 25;
/* максимальное значение поля TTL */
int nprobes = 1;
/* количество пробных пакетов */
int dport = 32768 + 666;
/* начальный порт получателя */
int datalen = sizeof(struct outdata);
/* длина поля данных UDP */

WSADATA wsaData;
WSAEVENT rawscEvent = WSA_INVALID_EVENT;

unsigned short checksum( unsigned short *buffer, int size);

int main(int argc, char **argv) {

    int iResult;
    int seq = 0;
    int code = 0;
    int done = 0;
    double rtt = 0.0;
    struct hostent *hp = NULL;
    struct outdata *outdata = NULL;
    unsigned char data[128];
    struct icmp *icmp_hdr = (struct icmp *) data;
    //    struct _SYSTEMTIME tvrecv;
    struct sockaddr_in sockAddr;

    unsigned long ul = 1;
    int nRet;
    //ініціюємо сокет
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <hostname>\n", argv[0]);
        exit(-1);
    }

    if ( (hp = gethostbyname(argv[1])) == NULL) {
        printf("gethostbyname() failed");
        exit(-1);
    }

    if ( (recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == SOCKET_ERROR) {
        printf("socket() failed, %d\n", WSAGetLastError());
        WSACleanup();
        exit(-1);
    }

    if((rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT) {
        printf("WSACreateEvent failed %d\n", WSAGetLastError());
        return -1;
    }


    if(WSAEventSelect(recvfd, rawscEvent, FD_READ) == SOCKET_ERROR) {
        printf("WSAEventSelect failed %d\n", WSAGetLastError());
        return -1;
    }

    if ((sendfd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) {
        printf("socket() failed, %d\n", WSAGetLastError());
        WSACleanup();
        exit(-1);
    }

    sport = (_getpid() & 0xffff) | 0x8000;
    /* номер порта UDP отправителя */

    ZeroMemory(&sasend, sizeof(sasend));
    sasend.sin_family = AF_INET;
    sasend.sin_addr= *((struct in_addr *) hp->h_addr);

    sabind.sin_family = AF_INET;
    sabind.sin_port = htons(sport);
    if (bind(sendfd, (struct sockaddr *)&sabind, sizeof(sabind)) != 0)
        printf("bind() failed");

    //отправляем пакет ехо, чтобы можно было принимать icmp(непонятный баг, но работает)
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    ZeroMemory(data, sizeof(data));
    icmp_hdr->icmp_type = ICMP_ECHO;
    icmp_hdr->icmp_code = 0;
    icmp_hdr->icmp_id = 1;
    icmp_hdr->icmp_seq = 1;
    icmp_hdr->icmp_cksum = 0;
    memset( &data[sizeof(struct icmp)],'X', sizeof(data)-sizeof(struct icmp));
    icmp_hdr->icmp_cksum = checksum( (unsigned short *) data, sizeof(data));

    if( sendto(recvfd, data, sizeof(icmp_hdr), 0, (struct sockaddr *) &sockAddr,
        sizeof(sockAddr)) == SOCKET_ERROR )
        printf( "Error of sendto, error code %u\n", WSAGetLastError());


    for (ttl = 1; ttl <= max_ttl && done == 0; ttl++) {
        iResult = setsockopt(sendfd, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));
        ZeroMemory(&salast, sizeof(salast));


        printf("%2d  ", ttl);
        fflush(stdout);

        for (probe = 0; probe < nprobes; probe++) {
            outdata = (struct outdata *)sendbuf;
            outdata->outdata_seq = ++seq;
            outdata->outdata_ttl = ttl;

            outdata->timestamp = GetTickCount();
            sasend.sin_port = htons(dport + seq);

            if (sendto(sendfd, sendbuf, datalen, 0, (struct sockaddr *)&sasend, sizeof(sasend)) < 0) {
                printf("sendto() failed");
                WSACleanup();
                exit(-1);
            }
        }

        packet_ok(seq);
    }
}


int packet_ok(int seq) {
    int len;
    int hlen1;
    int hlen2;
    struct iphdr *ip;
    struct iphdr *hip;
    struct icmp *icmp;
    struct udphdr *udp;

    int count=0, iResult = 0;
    DWORD rv = 2;
    BOOL bResult = FALSE;
    BOOL success = TRUE;

    len = sizeof(sarecv);

    do {
        WSANETWORKEVENTS info;
        rv = WSAWaitForMultipleEvents(1, &rawscEvent, FALSE, 4000, FALSE);

        switch(rv)   {
        case WSA_WAIT_EVENT_0:
            WSAResetEvent( rawscEvent );
            printf( "WSA_WAIT_EVENT_0\n" );
            if( WSAEnumNetworkEvents(recvfd, rawscEvent, &info) == SOCKET_ERROR )
                printf( "Can't enum network events for ICMP socket, error code %u", WSAGetLastError());
            else if( (info.lNetworkEvents & FD_READ) != 0 )
            {
                struct sockaddr_in sockAddr;
                unsigned char data[512];
                int bytes = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len);
                //пропустити перший пакет
                //if(n++==0)
                //  break;
                printf( "Has ICMP packet, %d bytes\n", bytes);
                success=FALSE;
            }
            break;
        case WSA_WAIT_TIMEOUT:
            printf( "WSA_WAIT_TIMEOUT\n" );
            success = FALSE;
            break;
        default:
            printf( "WSAEnumNetworkEvents error %u\n", WSAGetLastError());
            success = FALSE;
            break;
        }
    } while(success);

    ip = (struct iphdr *) recvbuf;    /* начало IP-заголовка */
    hlen1 = ip->ihl << 2;     /* длина IP-заголовка */
    icmp = (struct icmp *) (recvbuf + hlen1); /* начало ICMP-заголовка */
    /* начало сохраненного IP-заголовка */
    hip = (struct iphdr *) (recvbuf + hlen1 + 8);
    /* длина сохраненного IP-заголовка */
    hlen2 = hip->ihl << 2;
    /* начало сохраненного UDP-заголовка */
    udp = (struct udphdr *) (recvbuf + hlen1 + 8 + hlen2);

    printf("ip protocol: %d\n", ip->protocol);
     if (icmp->icmp_type == ICMP_TIMXCEED &&
    icmp->icmp_code == ICMP_TIMXCEED_INTRANS) {
      if (hip->protocol == IPPROTO_UDP &&
          udp->uh_sport == htons(sport) &&
          udp->uh_dport == htons(dport + seq))
        return (-2);
    } 
    
    if (icmp->icmp_type == ICMP_UNREACH) {
      if (hip->protocol == IPPROTO_UDP &&
        udp->uh_sport == htons(sport) &&
        udp->uh_dport == htons(dport + seq)) {        
    if (icmp->icmp_code == ICMP_UNREACH_PORT)
          return (-1);
      }      
    }
}

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


Теперь касательно разбора пакета. Допустим я хочу вывести протокол с айпи заголовка hip
Код

ip = (struct iphdr *) recvbuf;    /* начало IP-заголовка */
    hlen1 = ip->ihl << 2;     /* длина IP-заголовка */
    icmp = (struct icmp *) (recvbuf + hlen1); /* начало ICMP-заголовка */
    /* начало сохраненного IP-заголовка */
    hip = (struct iphdr *) (recvbuf + hlen1 + 8);
    /* длина сохраненного IP-заголовка */
    hlen2 = hip->ihl << 2;
    /* начало сохраненного UDP-заголовка */
    udp = (struct udphdr *) (recvbuf + hlen1 + 8 + hlen2);

    printf("ip protocol: %d\n", hip->protocol);
     if (icmp->icmp_type == ICMP_TIMXCEED &&
    icmp->icmp_code == ICMP_TIMXCEED_INTRANS) {
      if (hip->protocol == IPPROTO_UDP &&
          udp->uh_sport == htons(sport) &&
          udp->uh_dport == htons(dport + seq))
        return (-2);


Выводит 168, а должен 17(IPPROTO_UDP) . icmp->icmp_type, icmp->icmp_code выводятся с верными значениями. 

Причем, снифер WireShark, показывает, что протокол UDP(17).


Это сообщение отредактировал(а) wondertalik - 18.5.2012, 17:45
PM MAIL   Вверх
feodorv
Дата 18.5.2012, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  18.5.2012,  17:21 Найти цитируемый пост)
struct iphdr {
    u_int32_t ihl:4;
    u_int32_t version:4;

Где Вы взяли такое описание IP-заголовка??? Должно быть:
Код

    u_int8_t ihl:4;
    u_int8_t version:4;


Вообще, для начала было бы неплохо контролировать то, что пришло по сокету:
Код

    for( i = 0; i < bytes; i++) printf( "%s%.2x", (i == 0) ? "" : ".", recvbuf[i] & 0xffu);
    printf( "\n" );

И уже тут смотреть, 17 там или нет  smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 19.5.2012, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



[QUOTE=feodorv,18.5.2012,  21:12]
Цитата(wondertalik @  18.5.2012,  17:21 Найти цитируемый пост)

Где Вы взяли такое описание IP-заголовка??? Должно быть:
И уже тут смотреть, 17 там или нет  smile

Действительно не углядел. smile. Итак вот что в конечном итоге получилось. Быть может кому-то понадобится. Правда комментарии на украинском языке, так как это требование задания было.
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <process.h>
#include <time.h>
#include <windows.h>

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

#define BUFSIZE 1500
#define ICMP_TIMXCEED    11
#define ICMP_TIMXCEED_INTRANS 0
#define ICMP_UNREACH    3
#define ICMP_UNREACH_PORT    3
#define ICMP_ECHO 8

typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;

// стуктура даних UDP 
struct outdata {             
    int outdata_seq;        
    int outdata_ttl;        
    DWORD timestamp; 
};
//структура UDP заголовку
struct udphdr {
    u_short    uh_sport;        
    u_short    uh_dport;        
    u_short    uh_ulen;        
    u_short    uh_sum;            
};

//структура IP заголовку
struct iphdr {
    u_int8_t ihl:4;
    u_int8_t version:4;
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
};

//структура ICMP заголовку
struct icmp
{
    u_int8_t  icmp_type;    
    u_int8_t  icmp_code;    
    u_int16_t icmp_cksum;    
    union
    {
        struct ih_idseq    
        {
            u_int16_t icd_id;
            u_int16_t icd_seq;
        } ih_idseq;
    } icmp_hun;
#define    icmp_id        icmp_hun.ih_idseq.icd_id
#define    icmp_seq    icmp_hun.ih_idseq.icd_seq
    union
    {
        u_int8_t    id_data[1];
    } icmp_dun;
#define    icmp_data    icmp_dun.id_data
};


char recvbuf[BUFSIZE];
char sendbuf[BUFSIZE];

SOCKET sendfd =  INVALID_SOCKET; /* дескриптор сокету для відправлення UDP повідомлень */
SOCKET recvfd =  INVALID_SOCKET; /* дексриптор сокету для отримання ICMP-повідомлень */
/* структура sockaddr() для відправлення пакету */
struct sockaddr_in sasend;
/* структура sockaddr для прив'язування порту відправника */
struct sockaddr_in sabind;
/* структура sockaddr для отримання пакету */
struct sockaddr_in sarecv;
/* остання структура sockaddr отриманого пакету */
struct sockaddr_in salast;

int sport;
int dport;
int ttl;
int probe;
/* максимальне значення поля TTL */
int max_ttl = 25;
/* количество пробних пакетів */
int nprobes = 3;
/* початковий порт отримувача */
int dport = 32768 + 666;
/* довжина поля даних UDP */
int datalen = sizeof(struct outdata);

DWORD timepacket = 0;

WSADATA wsaData;
WSAEVENT rawscEvent = WSA_INVALID_EVENT;

int packet_ok(int seq);
unsigned short checksum( unsigned short *buffer, int size);

int main(int argc, char **argv) {

    int iResult;
    int seq = 0;
    int code = 0;
    int done = 0;
    double rtt = 0.0;
    struct hostent *hp = NULL;
    struct outdata *outdata = NULL;
    unsigned char data[128];
    struct icmp *icmp_hdr = (struct icmp *) data;
    struct sockaddr_in sockAddr;

    unsigned long ul = 1;
    //ініціюємо сокет
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup не вдалося ініціювати: %d\n", iResult);
        return 1;
    }

    if (argc != 2) {
        fprintf(stderr, "Використання: %s <ім'я або IP-адреса вузла>\n", argv[0]);
        exit(-1);
    }

    if ( (hp = gethostbyname(argv[1])) == NULL) {
        printf("помилка gethostbyname()");
        exit(-1);
    }

    if ( (recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == SOCKET_ERROR) {
        printf("помилка socket(), %d\n", WSAGetLastError());
        WSACleanup();
        exit(-1);
    }

    if((rawscEvent = WSACreateEvent()) == WSA_INVALID_EVENT) {
        printf("помилка WSACreateEvent %d\n", WSAGetLastError());
        return -1;
    }


    if(WSAEventSelect(recvfd, rawscEvent, FD_READ) == SOCKET_ERROR) {
        printf("помилка WSAEventSelect%d\n", WSAGetLastError());
        return -1;
    }

    if ((sendfd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) {
        printf("помилка socket(), %d\n", WSAGetLastError());
        WSACleanup();
        exit(-1);
    }
    //номер порту відправника
    sport = (_getpid() & 0xffff) | 0x8000;

    ZeroMemory(&sasend, sizeof(sasend));
    sasend.sin_family = AF_INET;
    sasend.sin_addr= *((struct in_addr *) hp->h_addr);

    sabind.sin_family = AF_INET;
    sabind.sin_port = htons(sport);
    if (bind(sendfd, (struct sockaddr *)&sabind, sizeof(sabind)) != 0)
        printf("bind() failed");


    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    ZeroMemory(data, sizeof(data));
    icmp_hdr->icmp_type = ICMP_ECHO;
    icmp_hdr->icmp_code = 0;
    icmp_hdr->icmp_id = 1;
    icmp_hdr->icmp_seq = 1;
    icmp_hdr->icmp_cksum = 0;
    memset( &data[sizeof(struct icmp)],'X', sizeof(data)-sizeof(struct icmp));
    icmp_hdr->icmp_cksum = checksum( (unsigned short *) data, sizeof(data));

    if( sendto(recvfd, data, sizeof(icmp_hdr), 0, (struct sockaddr *) &sockAddr,
        sizeof(sockAddr)) == SOCKET_ERROR )
        printf( "відправлення даних не вдалось, код помилки %u\n", WSAGetLastError());

    ZeroMemory(&salast, sizeof(salast));
    for (ttl = 1; ttl <= max_ttl && done == 0; ttl++) {
        iResult = setsockopt(sendfd, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));

        printf("%2d  ", ttl);
        fflush(stdout);

        for (probe = 0; probe < nprobes; probe++) {
            outdata = (struct outdata *)sendbuf;
            outdata->outdata_seq = ++seq;
            outdata->outdata_ttl = ttl;

            outdata->timestamp = timeGetTime();
            sasend.sin_port = htons(dport + seq);

            if (sendto(sendfd, sendbuf, datalen, 0, (struct sockaddr *)&sasend, sizeof(sasend)) < 0) {
                printf("відправлення даних не вдалось");
                WSACleanup();
                exit(-1);
            }
            if((code = packet_ok(seq)) == -3)
                printf("*");
            else {
                if (memcmp(&sarecv.sin_addr, &salast.sin_addr, sizeof(sarecv.sin_addr)) != 0) {

                    if ( (hp = gethostbyaddr(&sarecv.sin_addr, sizeof(sarecv.sin_addr), sarecv.sin_family)) != 0)
                        printf(" %s [%s]", hp->h_name, inet_ntoa(sarecv.sin_addr));
                    else
                        printf(" %s", inet_ntoa(sarecv.sin_addr));

                    memcpy(&salast.sin_addr, &sarecv.sin_addr, sizeof(salast.sin_addr));
                }

                rtt = (timepacket - outdata->timestamp);
                printf(" %.3f ms", rtt);
                if (code == -1)
                    ++done;
            }
            fflush(stdout);
        }

        printf("\n");
    }
}

//функція зчитує отримані ICMP-пакети
int packet_ok(int seq) {
    int len;
    int hlen1;
    int hlen2;
    struct iphdr *ip;
    struct iphdr *hip;
    struct icmp *icmp;
    struct udphdr *udp;
    DWORD rv;
    BOOL bResult = FALSE;
    BOOL success = TRUE;

    len = sizeof(sarecv);

    do {
        WSANETWORKEVENTS info;
        rv = WSAWaitForMultipleEvents(1, &rawscEvent, FALSE, 4000, FALSE);

        switch(rv)   {
        case WSA_WAIT_EVENT_0:
            WSAResetEvent( rawscEvent );
            if( WSAEnumNetworkEvents(recvfd, rawscEvent, &info) == SOCKET_ERROR )
                printf( "Can't enum network events for ICMP socket, error code %u", WSAGetLastError());
            else if( (info.lNetworkEvents & FD_READ) != 0 )
            {
                struct sockaddr_in sockAddr;
                unsigned char data[512];
                int bytes = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sarecv, &len);
                timepacket = timeGetTime();
                success=FALSE;
            }
            break;
        case WSA_WAIT_TIMEOUT:
            success = FALSE;
            return -3;
            break;
        default:
            printf( "WSAEnumNetworkEvents error %u\n", WSAGetLastError());
            success = FALSE;
            break;
        }
    } while(success);

    ip = (struct iphdr *) recvbuf;    /* початок IP-заголовка */
    hlen1 = ip->ihl << 2;     /* довжина IP-заголовка */
    icmp = (struct icmp *) (recvbuf + hlen1); /* початок ICMP-заголовка */
    /* початок збереженного IP-заголовка */
    hip = (struct iphdr *) (recvbuf + hlen1 + 8);
    /* довжина збереженного IP-заголовка */
    hlen2 = hip->ihl << 2;
    /* початок збереженного UDP-заголовка */
    udp = (struct udphdr *) (recvbuf + hlen1 + 8 + hlen2);

    if (icmp->icmp_type == ICMP_TIMXCEED &&
        icmp->icmp_code == ICMP_TIMXCEED_INTRANS) {
            if (hip->protocol == IPPROTO_UDP &&
                udp->uh_sport == htons(sport) &&
                udp->uh_dport == htons(dport + seq))
                return (-2);
    } 

    if (icmp->icmp_type == ICMP_UNREACH) {
        if (hip->protocol == IPPROTO_UDP &&
            udp->uh_sport == htons(sport) &&
            udp->uh_dport == htons(dport + seq)) {        
                if (icmp->icmp_code == ICMP_UNREACH_PORT)
                    return (-1);
        }      
    }
    return 0;
}

//функція для розрахунку контрольної суми
unsigned short checksum( unsigned short *buffer, int size)
{
    unsigned long cksum = 0;
    while( size > 1 )
    {
        cksum += *buffer++;
        size -= sizeof(unsigned short);
    }
    if( size != 0 ) cksum += *(unsigned char *) buffer;
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return (unsigned short) (~cksum);
}




feodorv, огромное спасибо Вам за помощь. С такими успехами у меня все меньше желания прогить под Виндоус. Быть может я и не прав))).

Это сообщение отредактировал(а) wondertalik - 23.5.2012, 19:16
PM MAIL   Вверх
feodorv
Дата 19.5.2012, 04:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(wondertalik @  19.5.2012,  02:59 Найти цитируемый пост)
у меня все меньше желания прогить под Виндоус

Это вопрос привычки)))
И Вы ещё сервисов не писали)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wondertalik
Дата 23.5.2012, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Код выше компилируется в визуал студио 2010 в режиме Debug. В release упорно не хочет. Выдает варнинги и ероры:

Код

Warning    2    warning C4101: 'data' : unreferenced local variable    C:\Documents and Settings\Admin\Мои документы\Visual Studio 2010\Projects\hello\hello\main.c    265    1    hello
Warning    3    warning C4101: 'sockAddr' : unreferenced local variable    C:\Documents and Settings\Admin\Мои документы\Visual Studio 2010\Projects\hello\hello\main.c    264    1    hello
Warning    1    warning C4133: 'function' : incompatible types - from 'IN_ADDR *' to 'const char *'    C:\Documents and Settings\Admin\Мои документы\Visual Studio 2010\Projects\hello\hello\main.c    218    1    hello


Error    5    error LNK1120: 1 unresolved externals    C:\Documents and Settings\Admin\Мои документы\Visual Studio 2010\Projects\hello\Release\hello.exe    1    1    hello
Error    4    error LNK2001: unresolved external symbol __imp__timeGetTime@0    C:\Documents and Settings\Admin\Мои документы\Visual Studio 2010\Projects\hello\hello\main.obj    hello
    7    IntelliSense: argument of type "IN_ADDR *" is incompatible with parameter of type "const char *"    c:\documents and settings\admin\мои документы\visual studio 2010\projects\hello\hello\main.c    218    31    hello
    6    IntelliSense: argument of type "unsigned char *" is incompatible with parameter of type "const char *"    c:\documents and settings\admin\мои документы\visual studio 2010\projects\hello\hello\main.c    189    21    hello



Как быть?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1252 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.