На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > sendto , функция возвращает ошибки по непонятным причинам
      Уважаемые форумчане, подскажите пожалуйста кто сталкивался с такой проблемой или хотя бы в каком месте копать.
      Суть проблемы такова. Пытаюсь выдавать ICMP пакеты. Написал класс, использующий функции библиотеки winsock2.h.
      Сам метод класса не стал пока выкладывать. Дело в том, ошибку возвращает функция sendto, в том случае, если
      раскомментировать закоментированные строчки кода. Т.е. если я пытаюсь отдать ей данные, веденные с формы.
      Как это связано я просто не могу понять. Среда C++Builder5. Думал может старый компилятор. Поставил Borland2007,
      перекинул исходники класса, ничего не меняя. Создал такую же форму с Edit и кнопочками, в общем повторил интерфейс
      полностью. И все заработало! Ну я подумал, проблема решена, но сегодня опять столкнулся с ошибкой функции sendto
      и опять по непонятной причине, но теперь уже ошибку вызывает объект Label на форме. Если он обновляется, то функция
      выдает ошибку, если его не трогать, то не выдает. Ошибку выдает 10013 - это в Borland2007 в пятом не помню, возможно такая же.
      Компилировал на другом компе - сначала не выдавал ошибку, потом что то на форме добавил - стал выдавать.
      Короче полная для меня неясность, если кто в курсе просветите!

      ExpandedWrap disabled
        //---------------------------------------------------------------------------
        void __fastcall TForm1::ButtonClick(TObject *Sender)
        {
         tICMP ICMP1;                        
         unsigned char DataOut[512];
         
        // unsigned char d = StrToInt(EditDataOut->Text);
         
         for (int i=0; i<100; i++)
            {
             DataOut[i] = 0x55;
        //     DataOut[i] = d;
            }
         
         AnsiString Res = ICMP1.SendData("192.168.1.1", DataOut, 100);
         if (Res != "OK")
            {
             ShowMessage(Res);
             return;
            }
        }
        //-----------------------------------------------------------------


      Добавлено
      Еще кое что вспомнил! Ошибка вылетает даже если раскоментировать только верхнюю строчку, т.е. где объявляется переменная char и ей присваивается
      значение из объекта Edit. Таким образом связь этих двух событий вообще становится непонятной..
        Columbo
        Цитата
        WSAEACCES
        10013 (0x271D)
        An attempt was made to access a socket in a way forbidden by its access permissions.

        Файрволл, антивирус случайно не блокируют твою программу? Какой-нибудь новый софт недавно устанавливал?
          Цитата Columbo @
          Еще кое что вспомнил! Ошибка вылетает даже если раскоментировать только верхнюю строчку, т.е. где объявляется переменная char и ей присваивается
          значение из объекта Edit.

          Практически сразу возникает вопрос - а что будет, если:
          ExpandedWrap disabled
            //---------------------------------------------------------------------------
            void __fastcall TForm1::ButtonClick(TObject *Sender)
            {
             tICMP ICMP1;                        
             unsigned char DataOut[512];
             
            // unsigned char d = StrToInt(EditDataOut->Text);
             
               unsigned char d = 0x55;
               for (int i=0; i<100; i++) { DataOut[i] = d; }
             
                AnsiString Res = ICMP1.SendData("192.168.1.1", DataOut, 100);
                if (Res != "OK")
                {
                 ShowMessage(Res);
                 return;
                }
            }
            //---------------------------------------------------------------------------

          Сомнительно выглядит возврат функции строкой.
          Достаточно вернуть NO_ERROR (=0), но это дело вкуса.
            Как всегда, форум не программистов, в экстрасенсов. Автор, где тобой написанный класс для ицмп?
            Примеров в сети два вагона, не пойму в чем проблема взять готовое
            http://tangentsoft.net/wskfaq/examples/dllping.html
            ?
              Спасибо за участие, коллеги!
              Итак начну отвечать в режиме LIFO:
              Цитата nemez @
              Автор, где тобой написанный класс для ицмп?
              Примеров в сети два вагона, не пойму в чем проблема взять готовое
              http://tangentsoft.net/wskfaq/examples/dllping.html
              ?

              Дело в том, что я хочу использовать ICMP пакеты для обмена данными, а в библиотеке ICMP.dll функция SendEchoRequest кажется ждет ответа без искажения данных, т.е. что послал - то и принял. А мне надо послал одно - принял что то другое.
              Вот метод класса:
              ExpandedWrap disabled
                AnsiString tICMP::SendData(char* ip_addres, unsigned char* OutBuf, size_t num)
                {
                 sockAddrLocal.sin_addr.S_un.S_addr = inet_addr(ip_addres);
                 sockAddrLocal.sin_family = AF_INET;
                 
                 pIcmpHeader = (struct icmp *) IcmpSendPacket;   // Point at the data area
                 pIcmpHeader->icmp_type = ICMP_ECHO;             // then fill in the data.
                 pIcmpHeader->icmp_code = 0;                     // Use the Sockman instance
                 pIcmpHeader->icmp_id = hInstance;               // handle as a unique ID.
                 pIcmpHeader->icmp_seq = 0;                      // It's important to reset
                 pIcmpHeader->icmp_cksum = 0;                    // the checksum to zero.
                 
                 iPacketSize = ICMP_HEADERSIZE + num;
                 
                 for (size_t i=ICMP_HEADERSIZE, j=0; j<num; i++, j++)
                    {
                     IcmpSendPacket[i] = OutBuf[j];
                    }
                 
                 pIcmpHeader->icmp_cksum = InternetChksum((LPWORD)pIcmpHeader, iPacketSize);
                 
                 if (pIcmpHeader->icmp_cksum !=0 )
                    {
                     iSentBytes = sendto(hSocket, (LPSTR) IcmpSendPacket, iPacketSize,
                     NO_FLAGS, (LPSOCKADDR) &sockAddrLocal, sizeof(sockAddrLocal));
                     if (iSentBytes == SOCKET_ERROR)
                        {
                         int err = WSAGetLastError();
                         return "Error.\r\nThe sendto() function returned a socket error: " + IntToStr(err);
                        }
                 
                     if (iSentBytes != iPacketSize)
                        {
                         return "Error.\r\nWrong number of bytes sent: " + IntToStr(iSentBytes);
                        }
                    }
                 
                 return "OK";
                }


              Повторюсь еще раз, программа работает, если не используется объект Edit, при этом не важно что записывается в массив: константа или переменная.
              Как строка из Edit влияет на функцию sendto - для меня тайна покрытая мраком.
              На другом компиляторе программа заработала и с Edit, но потом начала глючить при использовании объекта Label, причем зависит от того какая
              строка выводится на экран.

              Добавлено
              Цитата ЫукпШ @

              Сомнительно выглядит возврат функции строкой


              Ну просто так удобнее выводить на экран и придумывать коды не надо.
              По поводу Вашего примера реализации - будет работать, Edit же не используется.

              Добавлено
              Цитата Pacific @
              Файрволл, антивирус случайно не блокируют твою программу? Какой-нибудь новый софт недавно устанавливал?

              Нет ничего такого не делал. Опять повторюсь - пакеты высылаются, но при определенных обстоятельствах возникает облом.
                Есть ли уверенность, что размер (массива ?)"IcmpSendPacket"
                действительно не меньше "iPacketSize = ICMP_HEADERSIZE + num" ?
                  Кстати такой вопрос.
                  Вы испытываете свой проект в режиме дебага или делаете автономный экзешник (релиз)?
                    Он значительно больше - 1024 байта. Но будь он меньше, как бы это объясняло данную проблему? В массив кладутся байты, какая разница откуда они берутся?
                      Oleg2004 в режиме дебага
                        Цитата Columbo @
                        Он значительно больше - 1024 байта. Но будь он меньше, как бы это объясняло данную проблему? В массив кладутся байты, какая разница откуда они берутся?

                        Если бы он был меньше, то в этом цикле
                        ExpandedWrap disabled
                           
                          for (size_t i=ICMP_HEADERSIZE, j=0; j<num; i++, j++)  { IcmpSendPacket[i] = OutBuf[j]; }

                        будет выход за границы массива. С любыми последствиями.
                          Цитата Columbo @
                          в режиме дебага

                          Сетевые приложения так не отлаживаются.
                          Режим дебага зачастую - практически во всех средах разработки - достаточно трудно работает со стеком TCP/IP.
                          Это вам не поиск в базе данных отлаживать.
                          Потому я всегда требую от студентов делать релиз. Практика показала глючность режима дебага для сетевых приложений.
                          Сообщение отредактировано: Oleg2004 -
                            ЫукпШ это понятно... но тогда бы выход за пределы был всегда и почти всегда приводил бы к краху программы с соответствующими сообщениями. А тут ошибку возвращает функция, ничего не рушится, а если не использовать компонент Edit, то вообще все ок...

                            Добавлено
                            Oleg2004 Ваше замечание мне кажется наиболее точно объясняет такое поведение. Обязательно проверю это!
                              Цитата Columbo @
                              ничего не рушится, а если не использовать компонент Edit, то вообще все ок...

                              Во во... плавающий глюк вполне может быть именно в дебаге.
                                Цитата Columbo @
                                ЫукпШ это понятно... но тогда бы выход за пределы был всегда и почти всегда приводил бы к краху программы с соответствующими сообщениями.

                                Нет. Это как повезёт.
                                Поведение приложения типа "что-то глючит" как раз хорошо подходит
                                под гипотезу о выходе за пределы массива.
                                  Итак...
                                  На всякий случай увеличил размер массива до 2 кб, а потом до 4 - программа стала просто зависать при отправке.
                                  Сделал релиз - вываливает ту же ошибку.
                                  Переписал exe-шники в одельную папку (до этого запускал просто из билдера): релиз, релиз с библиотеками, дебаг - все программы зависают на передаче.

                                  Раскоментировал закоментированное в следующем коде:
                                  ExpandedWrap disabled
                                    AnsiString tICMP::Startup()
                                    {
                                     WSAStartup(0x0101, &wsaData);
                                     
                                     sockAddrHost.sin_family = AF_INET;
                                     sockAddrHost.sin_port = htons(0);
                                     sockAddrHost.sin_addr.s_addr = 0;
                                     
                                     if ((lpProtocolEntry = getprotobyname("icmp")) == NULL)
                                        {
                                         nProtocol = IPPROTO_ICMP;
                                        }
                                     else
                                        {
                                         nProtocol = lpProtocolEntry->p_proto;
                                        }
                                     
                                     if ((hSocket = socket(PF_INET, SOCK_RAW, nProtocol)) == INVALID_SOCKET)
                                        {
                                         return "Error.\r\nCould not create a RAW socket.";
                                        }
                                     
                                    /*
                                     int err = bind(hSocket, (sockaddr*)&sockAddrHost, sizeof(struct sockaddr_in));
                                     if(err == SOCKET_ERROR)
                                        {
                                         closesocket(hSocket);
                                         return "Error in bind(): " + IntToStr(err);
                                        }
                                     
                                     const char a = 1;
                                     if (setsockopt(hSocket, SOL_SOCKET, SO_BROADCAST, &a, 1) == SOCKET_ERROR)
                                        {
                                         closesocket(hSocket);
                                         return "Error in setsockopt";
                                        }
                                    */
                                     
                                     return "OK";
                                    }


                                  Ошибка перестала вываливаться программа стала передавать, ну и принимать естественно данные веденные с формы.
                                  Другая программа с похожими симптомами тоже перестала вываливать ошибку. Вот только меня терзают сомнения, что
                                  я уже это делал раньше. И почему биндинг сокета при использовании компонента Edit нужен, а без использования не нужен остается для меня загадкой.
                                  Какая разница откуда берутся данные? Причем тут броадкаст тоже не понятно, хотя я где то читал что для RAW сокетов эта опция нужна.
                                  В любом случае как говорится "будем посмотреть!" Завтра проверю на работе.
                                  Сообщение отредактировано: Columbo -
                                    Цитата Columbo @
                                    Переписал exe-шники в одельную папку (до этого запускал просто из билдера): релиз, релиз с библиотеками, дебаг - все программы зависают на передаче.

                                    Стабильность ошибки позволяет надеяться на ее локализацию. :)
                                    Цитата Columbo @
                                    Причем тут броадкаст тоже не понятно, хотя я где то читал что для RAW сокетов эта опция нужна.

                                    Нет. Эта опция совершенно не нужна. Зачем?
                                      Columbo, попробуй так:
                                      ExpandedWrap disabled
                                        ...
                                        int err = bind(hSocket, (sockaddr*)&sockAddrHost, sizeof(sockAddrHost));
                                        ...
                                        Нашел где то в кодах такую идею:
                                        sendto(s, buf, sizeof(ICMP_HDR)+32, 0, (SOCKADDR *)&dest, sizeof(dest));
                                          Цитата Columbo @
                                          Вот метод класса:

                                          ну, господа туманные ежи..
                                          Мы работаем с raw sockets. Это автоматически обозначает, что мы должны формировать заголовок ip, потом все остальное

                                          ExpandedWrap disabled
                                            ipheader = (struct ip_header*)packet;
                                            icmp = (struct icmp_echo*)(packet+sizeof(struct ip_header));

                                          ну и далее,
                                          ExpandedWrap disabled
                                            ipheader->ver       = 4;    /*IPv4*/
                                            ipheader->hl        = 5;    /* This is the smallest possible value, our IP header is only 20 bytes */
                                            ipheader->tos       = 0;
                                            ipheader->totl      = sizeof(struct ip_header)+sizeof(struct icmp_echo);

                                          и понеслась по кочкам метла, в свою очередь,
                                          Цитата
                                          icmp->type = 8; /* icmp echo */
                                          icmp->code = 0; /* only valid value for echo or echo reply */
                                          icmp->identifier = 0x1337;
                                          icmp->sequence = ...

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

                                          Добавлено
                                          вот пример icmp под мелкософт если чо
                                          http://www.vijaymukhi.com/security/network/rawsockets.htm
                                          попробуй сначала собери консольную аппликацию под студией или своим древним как говно мамонта борландом, потом переходи к формам-кнопкам, иначе будешь неделю какать кирпичами и соберешь на форуме вокруг себя толпу телепатов (что уже сделано)
                                          Сообщение отредактировано: nemez -
                                            nemez а я думал ip заголовок формируется автоматически... Ну если это не так, почему все же удается посылать и принимать пакеты, ну за исключением описаных мною ситуаций, когда функция возвращает ошибку?

                                            Добавлено
                                            ЫукпШ, Oleg2004 не помогло..
                                            На другом компе фокус с биндингом и броадкастом не удался.. еще хуже стало - просто зависает программа.
                                            Сообщение отредактировано: Columbo -
                                              Цитата Columbo @
                                              ЫукпШ, Oleg2004 не помогло..
                                              На другом компе фокус с биндингом и броадкастом не удался.. еще хуже стало - просто зависает программа.

                                              Где-то выход за границы массива или портится стек. Или вместе.
                                              Это может быть где угодно в программе, а проявиться именно в этом месте.
                                              Легче начать другой проект сначала и по-проще - какой-нибудь консольный
                                              вариант исключительно для отладки класса.
                                              И двигаться мелкими шажками.
                                                ЫукпШ Вот я убрал из прогаммы обновление Label->Caption, точнее даже не убрал а просто убрал пару строк оттуда и прекрасно обменивался пакетами без ошибок. И какова вероятность того что в консольном варианте, где нет ничего лишнего все будет работать? Я думаю 100%. Так куда двигаться в такой ситуации?
                                                Попробую как рекомендует nemez сделать, только вот как можно на другой стороне принять мой пакет причем с анализом контрольной суммы и размер наверняка учитывается а айпи заголовке, если я его не формирую мне также не понятно... а он тем временем принимается без ошибок.
                                                Сообщение отредактировано: Columbo -
                                                  Цитата Columbo @
                                                  nemez а я думал ip заголовок формируется автоматически...

                                                  Так оно и есть, если не применяется опция IP_HDRINCL. :yes:
                                                  А идеологически я согласен с ЫукпШ
                                                    Oleg2004 я уже понял
                                                      nemez я не нашел где формируется заголовок айпи в коде по твоей ссылке..
                                                      ExpandedWrap disabled
                                                        main(int argc, char **argv)
                                                         
                                                        {
                                                         
                                                        d = WSAStartup (MAKEWORD(2,1),&ws);
                                                         
                                                        printf("WSAStartup Return Value=%d\n",d);
                                                         
                                                        s = WSASocket(AF_INET,SOCK_RAW, IPPROTO_ICMP ,NULL, 0,0);
                                                         
                                                        printf("Socket Return Value=%d\n",s);
                                                         
                                                        hp = gethostbyname(argv[1]);
                                                         
                                                        memcpy(&dest.sin_addr,hp->h_addr,hp->h_length);
                                                         
                                                        dest.sin_family = hp->h_addrtype;
                                                         
                                                        printf("hp=%x Ip Address=%s\n",hp,inet_ntoa(dest.sin_addr));
                                                         
                                                        pIcmpHeader = (IcmpHeader *) malloc(sizeof(IcmpHeader));
                                                         
                                                        pIcmpHeader->i_type = 8;
                                                         
                                                        pIcmpHeader->i_code = 0;
                                                         
                                                        pIcmpHeader->i_id = (USHORT)GetCurrentProcessId();
                                                         
                                                        pIcmpHeader->i_cksum = 0;
                                                         
                                                        pIcmpHeader->i_seq = 326;
                                                         
                                                        memset(pIcmpHeader->data ,'A', 32);
                                                         
                                                        pIcmpHeader->timestamp = GetTickCount();
                                                         
                                                        pIcmpHeader->i_cksum = checksum((USHORT *)pIcmpHeader,sizeof(IcmpHeader));
                                                         
                                                        d = sendto(s,(char *)pIcmpHeader,sizeof(IcmpHeader),0,(struct sockaddr*)&dest,sizeof(dest));
                                                         
                                                        printf("Sentto return value=%d\n",d);
                                                         
                                                        dummy = sizeof(dest);
                                                         
                                                        d = recvfrom(s ,databuf,1024,0,(struct sockaddr*)&dest,&dummy);
                                                         
                                                        printf("recvfrom return value=%d\n",d);
                                                         
                                                        pIpHeader = (struct IpHeader *)databuf;
                                                         
                                                        printf("len=%x TOS=%d Total length %d %d\n",pIpHeader->lenver,pIpHeader->tos,pIpHeader->totallen , htons(pIpHeader->totallen));
                                                         
                                                        printf("ident=%d Frag=%d TTL=%d Protocol=%d\n",pIpHeader->ident,
                                                         
                                                        pIpHeader->fragandflags,pIpHeader->ttl,pIpHeader->proto);
                                                         
                                                        printf("CheckSum=%d %d\n",pIpHeader->checksum , checksum((USHORT *)databuf,20+32+12));
                                                         
                                                        printf("Source IP=%s Dest Ip=%s\n",inet_ntoa(pIpHeader->sourceIP),inet_ntoa(pIpHeader->destIP));
                                                         
                                                        printf("dest=%s\n",inet_ntoa(dest.sin_addr));
                                                         
                                                        int size = pIpHeader->lenver & 0x0f;
                                                         
                                                        size = size * 4;
                                                         
                                                        size = size - 20;
                                                         
                                                        printf("Size of IP headers %d\n",size);
                                                         
                                                        if ( size > 0)
                                                         
                                                        {
                                                         
                                                        struct ipopt *pipopt;
                                                         
                                                        pipopt = (struct ipopt *)(databuf + 20);
                                                         
                                                        printf("code=%d len=%d ptr=%d\n",pipopt->code,pipopt->len,pipopt->ptr);
                                                         
                                                        int noofstr;
                                                         
                                                        noofstr = (pipopt->ptr/4) - 1;
                                                         
                                                        printf("No of addr's=%d\n",noofstr);
                                                         
                                                        for ( i = 0 ; i < noofstr ; i++)
                                                         
                                                        {
                                                         
                                                        struct in_addr a;
                                                         
                                                        a.S_un.S_addr = pipopt->addr[i];
                                                         
                                                        printf("%s\n",inet_ntoa(a));
                                                         
                                                        }
                                                         
                                                        }
                                                         
                                                        }


                                                      структура заголовка заполняется уже после принятия пакета, это другая история, а перед отправкой - нет.
                                                      Сообщение отредактировано: Columbo -
                                                        Цитата Columbo @
                                                        ЫукпШ Вот я убрал из прогаммы обновление Label->Caption, точнее даже не убрал а просто убрал пару строк оттуда и прекрасно обменивался пакетами без ошибок.

                                                        Размеры программы изменились, возможно изменилось расположение кодов относительно данных.
                                                        По прежнему что-то портится, только в другом месте и в этой точке приложения не проявляется.
                                                          Цитата Columbo @
                                                          nemez я не нашел где формируется заголовок айпи в коде по твоей ссылке..

                                                          ExpandedWrap disabled
                                                            ipopt.code = 7;
                                                            ipopt.ptr  = 4;
                                                            ipopt.len  = 39;
                                                            setsockopt (s, IPPROTO_IP, IP_OPTIONS,(char *)&ipopt, sizeof(ipopt));
                                                            .....


                                                          вот тебе пдфочка
                                                          http://www.beknowledge.com/wp-content/uplo...2010/09/892.pdf
                                                          см. поиском функцию (<Ctrl-f>)
                                                          void DecodeIPOptions(char *buf, int bytes)
                                                          Через структуру (struct ipopt в том исходнике что ты смотрел) через setsockopt передаются параметры заголовка ip.

                                                          зы. Собери консольный пинг с примера рабочий, это тебе облегчит задачу
                                                            пошел собирать...
                                                              Предлагаю вместо
                                                              ExpandedWrap disabled
                                                                unsigned char d = StrToInt(EditDataOut->Text);


                                                              ExpandedWrap disabled
                                                                unsigned int d = StrToInt(EditDataOut->Text);
                                                                Цитата Columbo @
                                                                ExpandedWrap disabled
                                                                  //---------------------------------------------------------------------------
                                                                  void __fastcall TForm1::ButtonClick(TObject *Sender)
                                                                  {
                                                                   tICMP ICMP1;                        
                                                                   unsigned char DataOut[512];
                                                                   
                                                                  // unsigned char d = StrToInt(EditDataOut->Text);
                                                                   
                                                                   for (int i=0; i<100; i++)
                                                                      {
                                                                       DataOut[i] = 0x55;
                                                                  //     DataOut[i] = d;
                                                                      }
                                                                   
                                                                   AnsiString Res = ICMP1.SendData("192.168.1.1", DataOut, 100);
                                                                   if (Res != "OK")
                                                                      {
                                                                       ShowMessage(Res);
                                                                       return;
                                                                      }
                                                                  }
                                                                  //-----------------------------------------------------------------

                                                                Что за говнокод?
                                                                Сплошной хардкодинг.
                                                                Это неприемлемо в коммерческом коде, отсюда ошибки.
                                                                    Это не дает ответа на мой вопрос
                                                                      Думаю, что
                                                                      ExpandedWrap disabled
                                                                        (EditDataOut == NULL)
                                                                        Очень интересно)
                                                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                        0 пользователей:


                                                                        Рейтинг@Mail.ru
                                                                        [ Script execution time: 0,1309 ]   [ 17 queries used ]   [ Generated: 25.04.24, 09:42 GMT ]