Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.220.178.207] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Уважаемые форумчане, подскажите пожалуйста кто сталкивался с такой проблемой или хотя бы в каком месте копать.
Суть проблемы такова. Пытаюсь выдавать ICMP пакеты. Написал класс, использующий функции библиотеки winsock2.h. Сам метод класса не стал пока выкладывать. Дело в том, ошибку возвращает функция sendto, в том случае, если раскомментировать закоментированные строчки кода. Т.е. если я пытаюсь отдать ей данные, веденные с формы. Как это связано я просто не могу понять. Среда C++Builder5. Думал может старый компилятор. Поставил Borland2007, перекинул исходники класса, ничего не меняя. Создал такую же форму с Edit и кнопочками, в общем повторил интерфейс полностью. И все заработало! Ну я подумал, проблема решена, но сегодня опять столкнулся с ошибкой функции sendto и опять по непонятной причине, но теперь уже ошибку вызывает объект Label на форме. Если он обновляется, то функция выдает ошибку, если его не трогать, то не выдает. Ошибку выдает 10013 - это в Borland2007 в пятом не помню, возможно такая же. Компилировал на другом компе - сначала не выдавал ошибку, потом что то на форме добавил - стал выдавать. Короче полная для меня неясность, если кто в курсе просветите! //--------------------------------------------------------------------------- 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. Таким образом связь этих двух событий вообще становится непонятной.. |
Сообщ.
#2
,
|
|
|
Columbo
Цитата WSAEACCES 10013 (0x271D) An attempt was made to access a socket in a way forbidden by its access permissions. Файрволл, антивирус случайно не блокируют твою программу? Какой-нибудь новый софт недавно устанавливал? |
Сообщ.
#3
,
|
|
|
Цитата Columbo @ Еще кое что вспомнил! Ошибка вылетает даже если раскоментировать только верхнюю строчку, т.е. где объявляется переменная char и ей присваивается значение из объекта Edit. Практически сразу возникает вопрос - а что будет, если: //--------------------------------------------------------------------------- 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), но это дело вкуса. |
Сообщ.
#4
,
|
|
|
Как всегда, форум не программистов, в экстрасенсов. Автор, где тобой написанный класс для ицмп?
Примеров в сети два вагона, не пойму в чем проблема взять готовое http://tangentsoft.net/wskfaq/examples/dllping.html ? |
Сообщ.
#5
,
|
|
|
Спасибо за участие, коллеги!
Итак начну отвечать в режиме LIFO: Цитата nemez @ Автор, где тобой написанный класс для ицмп? Примеров в сети два вагона, не пойму в чем проблема взять готовое http://tangentsoft.net/wskfaq/examples/dllping.html ? Дело в том, что я хочу использовать ICMP пакеты для обмена данными, а в библиотеке ICMP.dll функция SendEchoRequest кажется ждет ответа без искажения данных, т.е. что послал - то и принял. А мне надо послал одно - принял что то другое. Вот метод класса: 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 @ Файрволл, антивирус случайно не блокируют твою программу? Какой-нибудь новый софт недавно устанавливал? Нет ничего такого не делал. Опять повторюсь - пакеты высылаются, но при определенных обстоятельствах возникает облом. |
Сообщ.
#6
,
|
|
|
Есть ли уверенность, что размер (массива ?)"IcmpSendPacket"
действительно не меньше "iPacketSize = ICMP_HEADERSIZE + num" ? |
Сообщ.
#7
,
|
|
|
Кстати такой вопрос.
Вы испытываете свой проект в режиме дебага или делаете автономный экзешник (релиз)? |
Сообщ.
#8
,
|
|
|
Он значительно больше - 1024 байта. Но будь он меньше, как бы это объясняло данную проблему? В массив кладутся байты, какая разница откуда они берутся?
|
Сообщ.
#9
,
|
|
|
Oleg2004 в режиме дебага
|
Сообщ.
#10
,
|
|
|
Цитата Columbo @ Он значительно больше - 1024 байта. Но будь он меньше, как бы это объясняло данную проблему? В массив кладутся байты, какая разница откуда они берутся? Если бы он был меньше, то в этом цикле for (size_t i=ICMP_HEADERSIZE, j=0; j<num; i++, j++) { IcmpSendPacket[i] = OutBuf[j]; } будет выход за границы массива. С любыми последствиями. |
Сообщ.
#11
,
|
|
|
Цитата Columbo @ в режиме дебага Сетевые приложения так не отлаживаются. Режим дебага зачастую - практически во всех средах разработки - достаточно трудно работает со стеком TCP/IP. Это вам не поиск в базе данных отлаживать. Потому я всегда требую от студентов делать релиз. Практика показала глючность режима дебага для сетевых приложений. |
Сообщ.
#12
,
|
|
|
ЫукпШ это понятно... но тогда бы выход за пределы был всегда и почти всегда приводил бы к краху программы с соответствующими сообщениями. А тут ошибку возвращает функция, ничего не рушится, а если не использовать компонент Edit, то вообще все ок...
Добавлено Oleg2004 Ваше замечание мне кажется наиболее точно объясняет такое поведение. Обязательно проверю это! |
Сообщ.
#13
,
|
|
|
Цитата Columbo @ ничего не рушится, а если не использовать компонент Edit, то вообще все ок... Во во... плавающий глюк вполне может быть именно в дебаге. |
Сообщ.
#14
,
|
|
|
Цитата Columbo @ ЫукпШ это понятно... но тогда бы выход за пределы был всегда и почти всегда приводил бы к краху программы с соответствующими сообщениями. Нет. Это как повезёт. Поведение приложения типа "что-то глючит" как раз хорошо подходит под гипотезу о выходе за пределы массива. |
Сообщ.
#15
,
|
|
|
Итак...
На всякий случай увеличил размер массива до 2 кб, а потом до 4 - программа стала просто зависать при отправке. Сделал релиз - вываливает ту же ошибку. Переписал exe-шники в одельную папку (до этого запускал просто из билдера): релиз, релиз с библиотеками, дебаг - все программы зависают на передаче. Раскоментировал закоментированное в следующем коде: 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 сокетов эта опция нужна. В любом случае как говорится "будем посмотреть!" Завтра проверю на работе. |