mantech 35 15 октября, 2019 Опубликовано 15 октября, 2019 · Жалоба Приветствую. Решил сделать на данном стеке несколько соединений, 2 клентских соединения с различными серверами и одно серверное, т.е. удаленный клиент может заходить на мой "сервер". Вопрос - как разделять эти соединения? В lwip это делалось с помощью PCB или передачи адреса в аргументе, здесь подобного нет, есть только упоминание на какой-то указатель appcall, но в примерах автор намудрил все это со своей "полуосью" protothread и разбираться в данной теме довольно утомительно. Может кто делал что-то подобное без всяких треадов и пр. буду рад, если поделитесь... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GeorgK 1 16 октября, 2019 Опубликовано 16 октября, 2019 · Жалоба Там разве не по адресам-портам в том числе исходящим пакеты определяются? И по уникальному номеру соединения TCP. насколько помню, без проблем делал несколько "серверов" - DHCP, DNS, httpd. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 16 октября, 2019 Опубликовано 16 октября, 2019 · Жалоба 2 часа назад, GeorgK сказал: И по уникальному номеру соединения TCP. Где он находится, не подскажете? Я так понимаю, когда делаю connect мне его нужно где-то получить и когда я пападаю в appcall снова его откуда-то взять и уже идентифицировать, из какого соединения пришел коллбэк, так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 17 октября, 2019 Опубликовано 17 октября, 2019 · Жалоба В 16.10.2019 в 10:04, mantech сказал: Где он находится, не подскажете? Я так понимаю, когда делаю connect мне его нужно где-то получить и когда я пападаю в appcall снова его откуда-то взять и уже идентифицировать, из какого соединения пришел коллбэк, так? Видимо никто не знает или не хочет рассказать, ну да ладно, тогда более конкретизирую вопрос. Допустим создал я 3 соединения с помощью функции connect(). Получил 3 указателя на структуры соединений. Теперь надо отправить данные в адрес второго соединения, но в функции uip_send есть только указатель на буфер данных и длина передаваемых данных. Как "объяснить" ей, что данные должны уйти по адресу, указанному при соединении номер 2, а не 1 или 3?? Может по-тупому выражаюсь - не спец в сетевых стеках. Если это нельзя сделать в принципе, порекомендуйте простой стек без использования динамической памяти, где это можно сделать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 17 октября, 2019 Опубликовано 17 октября, 2019 · Жалоба 49 minutes ago, mantech said: . . . но в функции uip_send есть только указатель на буфер данных и длина передаваемых данных. Как "объяснить" ей, что данные должны уйти по адресу, указанному при соединении номер 2, а не 1 или 3?? . . . Посмотрите в заголовочных файлах API какие ф-ии есть вообще. Очень давно с этим работал, не помню, возможно найдется таже ф-ия (тоже имя) но с другим (большим, или в виде структуры) набором аргументов, или какое-нибудь sendTo. Чем могу . . . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GeorgK 1 17 октября, 2019 Опубликовано 17 октября, 2019 · Жалоба Извиняюсь заранее, если это прописные истины. Спойлер В структурах uip_conn и uip_udp_conn (см. фрагмент файла uip.h), создаваемой для каждого соединения TCP и UDP соответственно, есть поля, соответствующие номерам локального и удалённого портов соединения TCP, есть адрес IP той стороны соединения. /** * Представление в uIP соединения TCP. * * Структура uip_conn используется для идентификации соединения. Все поля, * кроме одного полагаются не изменяемыми приложением. Исключением является * поле appstate, назначение которого - хранить какие либо данные (например, * указатели на открытые файлы) приложения, связанные с этим соединением. * Тип этого поля должен быть определён в заголовочном файле "uipopt.h" */ struct uip_conn { uip_ipaddr_t ripaddr; /**< Адрес IP удалённой стороны. */ uint16_t lport; /**< Локальный (левый) порт TCP ("сетевой" порядок байт). */ uint16_t rport; /**< Удалённый ("правый") порт TCP ("сетевой" порядок байт). */ uint8_t rcv_nxt[4]; /**< Последовательный номер, ожидаемый на приём. */ uint8_t snd_nxt[4]; /**< Последовательный номер, посланный нами. */ uint16_t len; /**< Размер уже посланных данных. */ uint16_t mss; /**< Текущий макс. размер сегмента для соединеия. */ uint16_t initialmss; /**< Начальный макс. размер сегмента для соединеия. */ uint8_t sa; /**< Переменная для вычисления таймаута. */ uint8_t sv; /**< Переменная для вычисления таймаута. */ uint8_t rto; /**< Таймаут повторной передачи. */ uint8_t tcpstateflags; /**< Состояние и флаги TCP. */ uint8_t timer; /**< Таймер повторной передачи. */ uint8_t nrtx; /**< Количество повторных передач последнего переданного сегмента. */ /** Состояние приложения. */ uip_tcp_appstate_t appstate; }; /** * Указатель на текущее соединение TCP. * * Указатель uip_conn может быть использован для доступа к * текущему соединению TCP. */ extern struct uip_conn *uip_conn; #if UIP_TCP /* Массив содержит все соединения uIP. */ extern struct uip_conn uip_conns[UIP_CONNS]; #endif /** * \addtogroup uiparch * @{ */ /** * Четырёхбайтовый массив для вычислений 32-х битного последовательного номера. */ extern uint8_t uip_acc32[4]; /** @} */ /** * Представление в uIP соединения UDP. */ struct uip_udp_conn { uip_ipaddr_t ripaddr; /**< Адрес IP удалённой стороны. */ uint16_t lport; /**< Локальный (левый) порт TCP ("сетевой" порядок байт). */ uint16_t rport; /**< Удалённый ("правый") порт TCP ("сетевой" порядок байт). */ uint8_t ttl; /**< Время жизни пакета (TTL) по умолчанию. */ /** Состояние приложения. */ uip_udp_appstate_t appstate; }; /** * Текущее соединение UDP. */ extern struct uip_udp_conn *uip_udp_conn; extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; struct uip_fallback_interface { void (*init)(void); void (*output)(void); }; В файле uipopt.h определяются подпрограммы для обработки соединений TCP и UDP: /** * \var #define UIP_APPCALL * * Имя прикладной функции, которую uIP должен использовать * при обработке событий TCP/IP. * */ #define UIP_APPCALL uip_server_appcall /** * \var #define UIP_UDP_APPCALL * * Имя прикладной функции, которую uIP должен использовать * при обработке событий UDP. * */ #define UIP_UDP_APPCALL uip_udp_server_appcall Прикладные программы (клиенты и серверы) фильтруют события по номеру локального или удалённого порта: void uip_server_appcall(void) { switch (uip_conn->lport) { case UIP_HTONS(HTTP_PORT): httpd_appcall(uip_conn->appstate); break; default: /* Соединение на незарегистрированный порт */ debug("uip_server_appcall: uip abort()\n"); uip_abort(); break; } } void uip_udp_server_appcall(void) { /* Вроде POLL по таймеру вызывается отдельно для каждого "соединения", так что должно работать */ #ifdef CONFIG_UIP_RESOLV if(uip_udp_conn->rport == UIP_HTONS(DNS_PORT)) { resolv_appcall(); return; } #endif if(uip_udp_conn->lport == UIP_HTONS(DNS_PORT)) { dns_appcall(); return; } if(uip_udp_conn->lport == UIP_HTONS(DHCP_CLIENT_PORT)) { dhcpc_appcall(); return; } if(uip_udp_conn->lport == UIP_HTONS(DHCP_SERVER_PORT)) { dhcps_appcall(); return; } if(uip_udp_conn->lport == UIP_HTONS(NBNS_PORT)) { nbns_appcall(); return; } } При необходимости дальнейшей индивидуальной работы с соединением используется поле (указатель или структура, как оно было определено в uipopt.h) appstate. Заполняется начальными значениями это поле при установлении соединения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 17 октября, 2019 Опубликовано 17 октября, 2019 (изменено) · Жалоба 3 часа назад, GeorgK сказал: При необходимости дальнейшей индивидуальной работы с соединением используется поле (указатель или структура, как оно было определено в uipopt.h) appstate. Это все я понял, в appstate задается главная коллбэк-функция, у меня вопрос в другом, как разделить какому соединению пришел "пинок" коллбэка, при условии, что соединений несколько, причем одновременно. Но тут есть кое-какое понимание, равно, как и по приему данных из удаленного хоста, а вот в передаче данных удаленному хосту - нет. Передача не ведется из коллбека, она должна вызываться из основной программы. Вот о б этом бы по-подробнее... ЗЫ. Смотрю сейчас и удивляюсь, или я тупой или автор сего поделья... Походу он даже не предусматривал такого, что программа может сама запросить передачу пакета удаленному хосту без "разрешения" стека: This function is used to send out a single segment of TCP * data. Only applications that have been invoked by uIP for event * processing can send data. Т.е. из основной программы я не имею права вызвать эту функцию, только из коллбека. А теперь вопрос, как я попаду в этот коллбэк, если удаленная сторона не передает пакеты, а ждет их от меня? Видимо только через вызов poll, и только тогда вызовется передача пакета в удаленный хост, и это офигенно быстро (период 0.5 сек!). Никакой другой функции, которая из основной программы может "пнуть" стек вызвать коллбэк для передачи я не увидел. Если это так, то такой стек только в топку... Изменено 17 октября, 2019 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GeorgK 1 18 октября, 2019 Опубликовано 18 октября, 2019 · Жалоба Вы совершенно правы, когда мне захотелось реализовать в загрузчике сетевую консоль (telnet, netconsole), именно по этой же причине пришлось переходить на lwIP - следующее поколение uIP и прикручивать многопоточность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 18 октября, 2019 Опубликовано 18 октября, 2019 (изменено) · Жалоба 1 час назад, GeorgK сказал: именно по этой же причине пришлось переходить на lwIP Я согласен, но этот стек мне не понравился, там все завязано на динамической памяти - шаг вправо, шаг влево - вылетаем в неустранимую ошибку, а шагов там этих, с учетом нескольких протоколов, по нескольку штук сокетов клиента и сервера, непредсказуемости работы самой сети, всяких случайных и не случайных разрывов и повторных соединений, причем все это асинхронно - и попасть в эту ошибку запросто, да еще траблы с выделением одной и той же pcb на разные коннекты, да и рестартануть стек нет возможности, только перезагрузка.... Это для меня неприемлимо. Кстати, кто что скажет про микрочиповский стек? Дам тоже везде "динамика" или что-то по устойчивее? Изменено 18 октября, 2019 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 5 22 октября, 2019 Опубликовано 22 октября, 2019 · Жалоба On 10/16/2019 at 7:07 AM, GeorgK said: Там разве не по адресам-портам в том числе исходящим пакеты определяются? Там какая-то наркомания с тем, куда в данный текущий момент указывает struct uip_udp_conn *uip_udp_conn; То есть я понимаю, конечно, что всё для фронта, всё для побе... лишь бы в мелкий 8-битник влезло, но с современными объемами памяти лучше использовать какие-то другие стеки, которые не позволят так легко стрелять себе в ногу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 22 октября, 2019 Опубликовано 22 октября, 2019 · Жалоба Может и вовсе проще будет написать свой UDP-стек с минимально нужным функционалом? UDP прост как два пальца. Нативная организация позволит упростить код и сделать его более предсказуемым. ИМХО, оптимально именно так, нежели пользоваться стеком почти 20-летней давности, о котором уже мало кто помнит. А ныне пользующихся и то меньше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба В 22.10.2019 в 21:35, Arlleex сказал: Может и вовсе проще будет написать свой UDP-стек с минимально нужным функционалом? UDP прост как два пальца. 1) Нужна работа именно с TCP. 2) Этим сейчас и занимаюсь (пишу свой стек, с использованием кусочков из uip, которые понимаю, как работают ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба 15 minutes ago, mantech said: 1) Нужна работа именно с TCP. 2) Этим сейчас и занимаюсь (пишу свой стек, с использованием кусочков из uip, которые понимаю, как работают ) В наше время писать свой стек TCP, ну это надо вообще от безделья томиться. Что, реально больше нечем заняться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GeorgK 1 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба Кстати, в lwIP есть свой менеджер памяти - самостоятельно раздаёт память из выделенной области. Или это именно он глючный? Я-то с проблемами со стороны стека не сталкивался, возможно, из-за слишком щадящих условий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 35 24 октября, 2019 Опубликовано 24 октября, 2019 · Жалоба 40 минут назад, GeorgK сказал: Кстати, в lwIP есть свой менеджер памяти - самостоятельно раздаёт память из выделенной области. К менеджеру памяти вопросов нет, он работает. Просто в самом стеке все не так однозначно, писал выше, что есть ситуации, при которых по докам все сделано правильно, но стек падает, редко, но все-таки. Система должна работать стабильно 24\7 с несколькими разнородными соединениями и не падать, допускается, если происходит падение стека, то система должна его восстановить без перезагрузок и зависаний. 2 часа назад, AlexandrY сказал: В наше время писать свой стек TCP, ну это надо вообще от безделья томиться. Я бы лучше от безделия потомился, но того, что удовлетворяет требованиям выше, или того, чтоб пол-года не портировать, не нашел... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться