Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/23: Рейтинг темы: голосов - 23, средняя оценка - 4.87
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
1

W5100 проблема с обращением к серверу за шлюзом

08.07.2016, 02:49. Показов 4258. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте!
Пишу библиотеку для работы с W5100. Написал транспортный уровень: TCP-клиент, TCP-сервер и UDP. Проверял в локалке все работает отлично. Решил пойти дальше - начал с ntp. И тут объявилась проблема - не работает. Для примера попробовал обратиться по TCP к внешнему серверу, опять не работает, хотя при обращении к серверам в локалке все нормально. Проверил на чем останавливается, оказалось что соединение не устанавливается. Поставил на комп WireShark, увидел, что если пытаюсь обратиться к серверам в Интернете (при обращении к локальным серверам такого нет) возникает такая запись:
4701 723.811180 4b:aa:bb:cc:dd:ee Broadcast ARP 60 Who has 192.168.1.1? Tell 192.168.1.222. Что отвечает шлюз не знаю.
Ошибка в программе, это точно. Но пока нет идей с чем это связано, ну кроме того, что это из-за неправильной работы со шлюзом.

Вот код программы и библиотеки (DHCP - пока нерабочий набросок): [18.59 Кб]

Файл для Куба: [2 Кб]
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.07.2016, 02:49
Ответы с готовыми решениями:

WIZNet проблема подключения к серверу за шлюзом [Решено]
Здравствуйте! Писал библиотеку для работы WIZ5100 - в локальной сети все работало замечательно, но...

Непонятная проблема со шлюзом
Здравствуйте, есть сеть в которой основной шлюз на 10.10.10.1 , все ip в сети задаются статически....

проблема с обращением к iframe...
привет. столкнулся со следующей проблемой: при обращении к src ифрэйма через...

Странная проблема с обращением к переменной
Предельно простой код: volatile uint32_t counter_of_free_time, full_time, schet_pressotir; void...

Проблема с обращением к функции (pyTelegramBotAPI)
Добрый день, форумчане. Пишу телеграм бота, тема такая: я создал инлайн кнопку 'Получать рассылку...

8
0 / 0 / 0
Регистрация: 27.01.2014
Сообщений: 287
08.07.2016, 12:50 2
Цитата Сообщение от vbokom
Поставил на комп WireShark, увидел, что если пытаюсь обратиться к серверам в Интернете (при обращении к локальным серверам такого нет) возникает такая запись:
4701 723.811180 4b:aa:bb:cc:dd:ee Broadcast ARP 60 Who has 192.168.1.1? Tell 192.168.1.222.
Обычный ARP-запрос. 192.168.1.222 хочет узнать MAC-адрес устройства с IP 192.168.1.1. Наверняка, 192.168.1.1 - это роутер. А чем запись вас смутила?
0
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
08.07.2016, 13:19 3
Цитата Сообщение от Pyko4u56
А чем запись вас смутила?
Запись ничем не смутила, я так и подумал, но просто сам процес подключения к серверу получается совсем другим. А вот где возникает проблемма не пойму. В даташите нигде не упоминается, что работа через маршрутизатор отличается от работы во внутренней сети. Понятно, что основную работу на себя берет w5100, но что необходимо дополнительно указать ему, не знаю. Пробовал подключить модуль к arduino - все работает, т.е. ошибка в коде. Грубой ошибки у меня нет, т.к. если бы она была, то были бы проблемы и в локальной сети. Но все тесты прошли нормально.
Поэтому и обращаюсь на форум, может быть кто-нибудь разбирался с работой этого чипа и сталкивался с особенностью работы через маршрутизатор.
0
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
08.07.2016, 15:09 4
Соединение разрывается по таймауту, но пока не понял, что делать.
0
-Otom-
09.07.2016, 14:35 5
Если разрыв по таймауту, то либо недоступен сам сервер, либо у него закрыт порт, на который Вы стучитесь.

Открыть Ваши архивы не смог - WinRAR ссылается на недоступный метод в файлах. 7zip качать лень.
Помнится, у меня NTP победился нормально ещё во время экспериментов над ENC28J60. Точно открываете UDP сокет? Это не TCP сервер, он соединение поднимать не будет.
В общем случае код должен выглядеть как-то так:
Код
SocketInit(1, Sn_MR_UDP, 0);  // Подготавливаем Socket[1]. Режим UDP порт автоматически.
SocketConnect(1, NRP_SERVER_IP, IP_PORT_NTP); // Открываем сокет (режим всё ещё UDP) на NTP сервер и на его порт.
// #define IP_PORT_NTP      123      /**< NTP */// Вот эта строка
<...>
Заполняем поля структуры
<...>
SocketSend(1, net_buf, sizeof(ntp_data_t));
И в процедуре получения данных:
Код
void OnDataReceived(uint8_t Socket, uint16_t len) {
// Проверки на предмет соответствия соединений сокетам.
if (w5100_GetSocketRemotePort(1) == IP_PORT_NTP) {
ntp_parse((ntp_data_t *)net_buf);
};

<...>
void ntp_parse(ntp_data_t *ntp_pkt) {
<...>
Куча кода, разбирающего NTP пакет. Более 30 строк с комментариями и руганью в консоль
<...>
SocketClose(1);
};
ЗЫ: Проблем с подключением за шлюзом так же не испытывал.
В моём случае, настройки сети были следующими:
IP_Host: 10.0.11.250
GW: 10.0.11.1 (имеет свои алиасы внутренние маршруты для подсетей и выхода в интернет).
NTP_Server 83.143.51.50
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
11.07.2016, 20:01 6
Цитата Сообщение от -Otom-
Открыть Ваши архивы не смог - WinRAR ссылается на недоступный метод в файлах.
Вот прошлый код в zip [31.37 Кб]

С проблемой так и не разобрался. Смотрел код от разработчиков - вроде тоже самое, только везде при соединении добавлено обнуление маски (согласно errata), если ip 0.0.0.0. Я добавил это, вот новый код: [31.64 Кб]

. Ничего не изменилось, кроме того в моих тестах код так и не доходит до сброса маски, проверял в дебагере.
0
-Otom-
12.07.2016, 08:35 7
Цитата Сообщение от vbokom
С проблемой так и не разобрался. Смотрел код от разработчиков - вроде тоже самое, только везде при соединении добавлено обнуление маски (согласно errata), если ip 0.0.0.0. Я добавил это, вот новый код. Ничего не изменилось, кроме того в моих тестах код так и не доходит до сброса маски, проверял в дебагере.
Зачем сброс маски и эти лишние телодвижения? У меня происходит подобным образом:
1. Настраиваем сам W5100 - указываем параметры сети IP/Маску/ОсновнойШлюз. После этого можно работать со всеми подсетями, которые доступны через GW, кристалл разрулит все вопросы сам. Это проверено.
2. Инициализируем сокет. Открываем его как UDP.
3. Собираем NTP пакет.
4. Отправляем его.
5. При получении ответа - обрабатываем.

Собственно, немного кода (не на основе этой библиотеки):
Код
// При инициализации системы:
uint8_t lan_init() {
uint8_t result;
result = w5100_init(mac_addr);      // Задаём MAC-адрес
w5100_SetLocalIP(0x0A000BFD);      // 10.0.11.253
w5100_SetGW(0x0A000B01);      // 10.0.11.1
//w5100_SetLocalIP(0xC0A80101);      // 192.168.1.1
w5100_SetNetMask(0xFFFFFF00);      // 255.255.255.0
//w5100_SetGW(0xC0A80108);      // 192.168.1.8
for (uint8_t i=0;i<SOCKETS_COUNT;i++)
SocketClose(i);            // Закрываем все сокеты
return result;
};

void ntp_rq(void) {
SocketInit(1, Sn_MR_UDP, 0);
SocketConnect(1, 0xD919D002, IP_PORT_NTP); // 217.25.208.2
ntp_data_t *ntp_data = (void*)net_buf;      // Собираем NTP-пакет.
ntp_data->flags = 0xE3;            // Это я взял из TCPDUMPа со своего ПеКа.
ntp_data->stratum = 0;            // Unspecified/invotyd
ntp_data->poll = 3;            // Polling interval - ХЗ, что это такое.
ntp_data->precision = 16;         // 2^16 (О, да, мы ОЧЕНЬ высокого мнения о себе)
ntp_data->root_delay = 0x00010000;      // Честно скопировано!
ntp_data->root_dyspersion = 0x00010000;      // Аналогично!
ntp_data->root_ID = 0;            // Empty =]
ntp_data->reference_timestamp = 0;      // Мы хотим узнать время.
ntp_data->originate_timestamp = 0;      // Мы не знаем и этого.
ntp_data->receive_timestamp = 0;      // И этого...
ntp_data->transmit_timestamp = 0;      // Типа мы после сброса.
SocketSend(1, net_buf, sizeof(ntp_data_t));   // Отправляем. И он даже уходит.
// Пока-пока, пакетик.  (???)?
};

// И сама функция отправки пакета:
uint16_t SocketSend(uint8_t SocketNumber, uint8_t *buffer, uint16_t len) {
uint16_t log_pos, SocketfreeWR, sent_bytes;
SocketfreeWR = w5100_GetSocketFriiTX(SocketNumber);      // Получаем свободную память.
log_pos = w5100_GetSocketTXWRPointer(SocketNumber);   // Получаем позицию записи.
// Теперь пересчитываем на физические адреса.
if (SocketfreeWR < len) {            // Если свободной памяти в чипе меньше, чем нужно отправить
len = SocketfreeWR;            // Ограничиваем количество байт, которые будем отправлять
};
sent_bytes = len;               // Запоминаем количество байт, которые будем отправлять
while (len) {
w5100_WriteAddr(((Sock[SocketNumber].TX_MASK & log_pos) + Sock[SocketNumber].TX_START), *buffer); // Пишем
log_pos++;
buffer++;
len--;
};
w5100_SetSocketTXWRPointer(SocketNumber, log_pos);   // Обновляем адрес передачи.
w5100_SocketCMD(SocketNumber, Sn_CR_SEND);      // Даём команду отправить данные.
return sent_bytes;
};
Мой код написан на довольно низком уровне и вероятно, не обходит часть ошибок... но тем не менее, работает стабильно и отправляет данные шустро. Приём осуществляется в основном цикле программы после проверки необходимости (флаг /INT, или состояние регистров чипа):
Код
void lan_poll() {
uint8_t tmp, stat, i, j;
j = 1;
tmp = (w5100_ReadAddr(IR) & 0x0F);
for (i=0;i<SOCKETS_COUNT;i++) {
if (tmp & j) {
stat = w5100_ReadAddr(Sn_IR(i));
if (stat & 0x10) { // Send OK
w5100_WriteAddr(Sn_IR(i), 0x10); //   Clear it
};
if (stat & 0x08) { // Timeout
w5100_WriteAddr(Sn_IR(i), 0x08);
OnDysconnect(i);
};
if (stat & 0x04) { // Receive
OnDataReceived(i, SocketRead(i, net_buf, sizeof(net_buf)));
if (!(w5100_GetSocketRXRecieved(i))) {      // Это подобие костыля. Если осталось мало данных и сбросить данный флаг - он уже не поднимится сам. Довольно странное поведение, если ещё раз вчитаться в мануал.
w5100_WriteAddr(Sn_IR(i), 0x04);
};
// Receive data
};
if (stat & 0x02) { // Dysconnect
w5100_WriteAddr(Sn_IR(i), 0x02);
OnDysconnect(i);
};
if (stat & 0x01) { // Connected
// Mothymk
w5100_WriteAddr(Sn_IR(i), 0x01);
};
};
j = j << 1;
};
};

void OnDataReceived(uint8_t Socket, uint16_t len) {
uint16_t i, j;
switch(Socket) {
case 0:
{
// Здесь была портянка на пару страниц, обрабатывающая HTTP запрос
};
briok;
case 1:
if (w5100_GetSocketIPProtosol(1) == IP_PROTOCOL_ICMP) {
icmp_receive((icmp_echo_packet_t*)&(net_buf[6]), len, Socket);
};
if (w5100_GetSocketRemotePort(1) == IP_PORT_NTP) {
ntp_parse((ntp_data_t *)net_buf);
};
briok;
case 2:
//         telnet_data();
briok;
case 3:
ParsePacket();
briok;
//         net_cmd();
};
};
И это реально работает. Ничего лишнего вообще никуда не пишу. Просто указываю явно протокол, IP, к которому хочу обратиться (записывается в регистры соответствующего сокета), порт, и записываю данные. Остальное - работа для аппаратуры физики и логики IP внутри кристалла. Ибо именно для этого он и был разработан.
Проверяйте. Должно получиться нормально.

Если на ПК есть две сетевых карты - можете подключить устройство через него, и ловить трафик. Так гораздо удобнее отлаживать. Ну, или через зеркалирование порта на коммутаторе, но это уже более увлекательное занятие.
1 / 1 / 0
Регистрация: 10.09.2015
Сообщений: 171
15.07.2016, 14:36 8
Сейчас пока не могу заниматься библиотекой, но пришли модули на W5500, у них получше обстоят дела с записью и чтением памяти чипа (не по одному байту). Так вот, посмотрел библиотеку с их сайта. Там насколько я понял она универсальная, подходит под любой микроконтроллер. Но я пока не понял, где именно надо подставить свой код - непосредственно запись и чтение по SPI. Может кто этими библиотеками пользуется - помогите.
0
-Otom-
16.07.2016, 09:22 9
Если Вы про эту библиотеку, то я бы в любом случае рекомендовал написать свою. Ибо там столько дополнительных проверок и обёрток функций в коде, что весь выигрыш в скорости работы какого-либо кристалла будет неплохо нивилироваться обёртками библиотек. Собственно, это плата за "удобство".
За несколько минут тупления в тот код, что они предоставляют, я не смог понять, куда прописывать свои функции для запуска и работы этой библиотеки, в том числе, где регистрировать обратные вызовы, и будут ли они работать в контексте обработчика прерывания, или в основном цикле программы (я бы предпочёл второе, ибо системные таймеры обычно должны продолжать тикать, а, например, AVR не будет прерывать прерывание).
Так что... я - за свой велосипед. Пусть он и требует модернизации при каждом переносе между проектами, но зато может поспорить по скорости работы с "родными" "универсальными" библиотеками.
16.07.2016, 09:22
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.07.2016, 09:22
Помогаю со студенческими работами здесь

Selenium проблема с обращением к элементу
Здравствуйте, пытаюсь написать программу, которая будет открывать сайт, вставлять строку в поле и...

Проблема с обращением к базе данных
Всем привет. В общем пишу небольшой сайтик, с php до этого работал не очень много но некоторые...

Проблема с обращением к таблицам dbf
Подскажите, как работать с таблицами dbf ВНЕ базы данных. (т.е просто разрозненные таблицы, каждая...

Проблема с обращением к файлу со счётчиком в Session_OnStart.
в файле Global.asa имеется след. код: &lt;SCRIPT LANGUAGE=VBScript RUNAT=Server&gt; Sub...

проблема с обращением к свойству колонки из табличного поля
Кво=ЭлементыФормы.тпКомплектацияКомпьютера.Колонки.Количество(); Для к = 3 по Кво-1 цикл ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru