|
IP/UDP/TFTP uIP v1.0, uIP-шники отзовитесь. |
|
|
|
Aug 10 2007, 11:31
|

Частый гость
 
Группа: Validating
Сообщений: 184
Регистрация: 26-06-07
Из: Санкт-Петербург
Пользователь №: 28 714

|
Недавно поднял uIP 1.0 для своей платы с LPC2364. Реализовал на ней web сервер, потом - telnet. Документация потрясающая, все понятно. Но это все были стеки IP/TCP/, моя же техническая задача состоит в реализации IP/UDP/TFTP(modbus). Если кто имеет исходнички на UDP и TFTP, плиз, ПОДЕЛИТЕСЬ. А если кто-то, вообще, уже делал такую связку, то я буду несказанно рад взять и воспользоваться вашими плодами работы безо всяких угрызений совести blush.gif. Попутно спрошу. 1. Я так понимаю, что в uIP есть возможность подключения нескольких соединений равно как и несколько портов, но последнее не означает, что в uIP можно врубить два сервака сразу, например, web сервер и telnet, поскольку существует только одно определение app_call, которое вызывается обработчиком событий TCP. Правильно я понимаю? 2. Могут ли одновременно работать TCP и UDP в uIP?
Спасибо за внимание.
|
|
|
|
2 страниц
< 1 2
|
 |
Ответов
(15 - 29)
|
Aug 20 2007, 12:51
|

Частый гость
 
Группа: Validating
Сообщений: 184
Регистрация: 26-06-07
Из: Санкт-Петербург
Пользователь №: 28 714

|
Кажется я ответил себе как отследить состояние каждого соединения для того, чтобы реализовать множественное подключение к моему серверу. Ответ был как всегда под руками и никаких дополнительных глобальных переменных, отслеживающих состояние сервера не надо. Ответ вот где:
struct uip_udp_conn { uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ u16_t lport; /**< The local port number in network byte order. */ u16_t rport; /**< The remote port number in network byte order. */ u8_t ttl; /**< Default time-to-live. */
/** The application state. */ uip_udp_appstate_t appstate; };
typedef struct tftp_state uip_udp_appstate_t;
struct tftp_state { u16_t opcode; /* Êîä îïåðàöèè */ u16_t block_id; /* Íîìåð áëîêà */ u8_t *data; /* Óêàçàòåëü íà äàííûå */ };
Делая так: struct uip_udp_conn *tftp_conn; // некое UDP-соединение tftp_conn = (struct uip_udp_conn*)uip_udp_conn; имеем доступ к состоянию текущего UDP-соединения (из таблицы UDP-соединений):
tftp_conn->appstate.opcode -код операции, которую данное соед. совершает (дает читать или записывать) tftp_conn->appstate.block_id -какой блок данных он дает читать/записывать tftp_conn->appstate.data -указатель на данные с которыми сервер должен сделать что-либо(записать/прочитать блок в/из файл).
Кому интересно:
Причем текущее соединение устанавливается только если: 1. в таблице UDP-соединений есть хоть одна запись с локальным номером порта TFTP(69 или иной не равный 0) 2. UDP-датаграмма предназначена именно порту текущего соединения 3. Текущее соединение "узнает" номер порта удаленного хоста или видит его впервые, но готов пообщаться, т.к. rport=0(типа сервер свободен и готов к новой связи) 4. Текущее соединение "узнает" IP-адрес удаленного хоста или видит его впервые, но готов пообщаться, т.к. tipaddr=0.0.0.0. (IP-адрес проверяет IP)
При входе в наш обработчик APP_CALL() (у меня это void tftp_appcall(void)) надо: 1. определить состояние флага uip_flags( либо UIP_POLL либо UIP_NEWDATA) 1.1. Если UIP_POLL, то проверить условие истечения таймаута 1.2. Если UIP_NEWDATA, то проверить для какого порта именно предназначен пакет: 1.2.1 Если для порта 69, то создать новое соединение tftp_conn = uip_udp_new(&ripaddr, rport) и обработать запрос (ничего другого быть и не может). 1.2.2 Если для нашего(а это проверялось еше в uip_process()), тогда обработать данные или подтверждение.
З.Ы. При закрытии соединения (удаления ее из таблицы UDP-соединений) обязательно обнулять поля ripaddr и rport. З.Ы. При инициализации надо создавать UDP-соединение в таблице под номером порта 69. void tftp_init(void) { uip_ipaddr_t addr; struct uip_udp_conn *c;
uip_ipaddr(&addr, 0,0,0,0); c = uip_udp_new(&addr, HTONS(0)); // Адрес и номер порта удаленного хоста нулевые. if(c != NULL) { uip_udp_bind(c, HTONS(69)); // Стандартный порт TFTP } }
|
|
|
|
|
May 22 2008, 07:21
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 1-02-07
Пользователь №: 24 931

|
уважаемый Цырен! поможите исходничком, а? не понимаю, как обрабатывать tftp_appcall (сущность его какая должна быть). заранее благодарен.
|
|
|
|
|
May 23 2008, 19:39
|

Местный
  
Группа: Участник
Сообщений: 374
Регистрация: 7-11-07
Из: Moscow
Пользователь №: 32 131

|
Цитата(Цырен @ Aug 20 2007, 16:51)  Кажется я ответил себе как отследить состояние каждого соединения для того, чтобы реализовать множественное подключение к моему серверу. Как я понял, вам нужен UDP сервер? Только что закончил такую разработку и прекрасно обошелся без готовых uIP, в которых сам черт ногу сломит. Суть проста. -Принимаем пакет, адресованный серверу по МАС, по IP, и по номеру порта. Выделяем запрос, обрабатываем его и выдаем пакет ответа в хидере которого, стоят МАС клиента, IP-клиента, и порт запроса клиента. Все эти данные выделяются из хидера запроса. Таким образом, UDP-сервер откликается всякому клиенту, кто грамотно к нему обратился. И никаких таблиц соединений и прочей лабуды не требуется. Кстати, скорость передачи потока данных в пакетах UDP размером 1.5К у меня на STR912FAW44 получилась 96 Мbit/s Получилась только потому, что никакого готового софта uIP не использовал.
|
|
|
|
|
Feb 5 2013, 12:17
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Подскажите с UDP на uIP v1.0. Никак не получается отправить пакет, хотя принимать получается. Код void uip_udp_appcall(void) { if(uip_udp_conn->lport == HTONS(BOOTETH_LISTENUDPPORT)) { //----------------- if(uip_newdata()) {udp_newdata(uip_udp_conn);} //----------------- } } обработчик принятых данных Код void udp_newdata(struct uip_udp_conn *udp_conn) { struct uip_udp_state *s = &(udp_conn->appstate); struct uip_udp_conn *udp_connection; uint8_t *pBuffer,i; uint32_t posnum=0; uint32_t BytesLeft=bMIN(UIP_CONF_BUFFER_SIZE,uip_datalen()); udp_connection=uip_udp_new(&udp_conn->ripaddr, udp_conn->rport); if(udp_connection==NULL) return; //------------------- //тут обработка полученных байт //------------------- uip_udp_remove(udp_connection);
} отправка буфера по UDP Код void ETH_EthUDPFindResponse(void) { //---------------------------------- //формирование буфера //---------------------------------- //memcpy(uip_appdata,ETH_TransmitBuffer,Len); //uip_udp_send(Len); //uip_send(ETH_TransmitBuffer,(uint32_t)pBuffer-(uint32_t)ETH_TransmitBuffer); uip_slen = Len; memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], ETH_TransmitBuffer, Len > UIP_BUFSIZE? UIP_BUFSIZE: Len); uip_process(UIP_UDP_SEND_CONN); uip_slen = 0; } Может есть у кого рабочий пример с UDP?
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Feb 5 2013, 12:17
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
а lwip слишком тяжел? По мне так продвинутее на порядок
|
|
|
|
|
Feb 5 2013, 12:18
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Цитата(podelkin @ Feb 5 2013, 16:17)  а lwip слишком тяжел? По мне так продвинутее на порядок Да, это проект bootloader'a, чем меньше размер тем лучше. lwIP используется в основной прошивке.
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Feb 6 2013, 19:08
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Цитата(scifi @ Feb 5 2013, 19:08)  Есть рабочий пример. Как раз загрузчик. Спасибо за пример, но что-то не получается. Вроде все так же делаю, а в чем причина не пойму. Может какую-нибудь мелочь упустил? Во вложении проект в Keil и приложение для отправки UDP пакетов. Только увидел, что у меня более старая версия uIP. Попробую завтра с вашей версией.
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Feb 7 2013, 09:27
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Одна проблема решилась. Оказывается uip шлет udp сообщения, но адрес получателя и порт нулевые, поэтому ближайший роутер отбрасывает это сообщение и я в Wireshark'е на компе его не вижу. После подключения STM к компу на прямую, сообщения стали видны, но проблема с неправильным адресом получателя и портом осталась. Насколько я понял, происходит это из-за того что при отправке сообщения uip использует первую структуру(соединение) Код struct uip_udp_conn , в которой как раз и есть все нули в поле адреса и порта. Пробовал присвоить указателю Код uip_udp_conn адрес структуры, полученной при создании нового соединения, но тогда сообщения вообще не отправляются. CODE void udp_newdata(struct uip_udp_state *s) { struct uip_udp_conn *udp_connection; struct uip_udpip_hdr *hdr; uint8_t *pBuffer; uint32_t BytesLeft=bMIN(UIP_CONF_BUFFER_SIZE,uip_datalen()); hdr = (struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]; udp_connection= uip_udp_new(&hdr->srcipaddr, hdr->srcport); if(udp_connection==NULL) return; memcpy(s->inputbuffer,uip_appdata,BytesLeft); pBuffer=(uint8_t*)&s->inputbuffer; if(memcmp(pBuffer,tcp_startnewmessage,sizeof(tcp_startnewmessage))==0) { uip_udp_conn = udp_connection; //<<<<<<< присваиваем новый указатель ETH_SendUDPResponse(); } uip_udp_remove(udp_connection);
} P.S. uIP из моего проекта.
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Feb 7 2013, 10:55
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Наконец я победил uip:) Как и думал проблема заключалось в одном маленьком недочете: При начальной инициализации udp вместо нулевого указателя на адрес удаленного хоста Код udp_conn = uip_udp_new(0, 0); я передавал указатель на структуру Код uip_ipaddr_t с забитыми нулями Код uip_ipaddr(ipaddr, 0,0,0,0); udp_conn = uip_udp_new(&ipaddr, 0);
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Aug 20 2013, 10:31
|
Группа: Новичок
Сообщений: 3
Регистрация: 6-11-10
Пользователь №: 60 693

|
Добрый день. Что-то не получается у меня отправить данных с МК на комп. Отвечать на сообщения с компа я умею, колбэки вызываются, там обрабатываю пакеты, отправляю ответы в виде uip_send(). Но вся беда в том, что uip_send() нужно вызывать только в качестве ОТВЕТА на запрос с компа.
А как сделать так, чтобы независимо слать данные с МК на комп? Чтобы через WireShark видеть что что-то шлется..?
|
|
|
|
|
Sep 20 2013, 11:45
|
Группа: Новичок
Сообщений: 2
Регистрация: 12-09-13
Пользователь №: 78 288

|
Цитата(PoReX @ Feb 7 2013, 14:55)  Наконец я победил uip:) Как и думал проблема заключалось в одном маленьком недочете: При начальной инициализации udp вместо нулевого указателя на адрес удаленного хоста Код udp_conn = uip_udp_new(0, 0); я передавал указатель на структуру Код uip_ipaddr_t с забитыми нулями Код uip_ipaddr(ipaddr, 0,0,0,0); udp_conn = uip_udp_new(&ipaddr, 0); Столкнулся с такой же проблемой: адрес и порт получателя нулевые, хотя нулевой указатель передаю и адрес структуры при получении сообщения. Вы не могли бы выложить свою программу для контроллера, отвечающую за отправку UDP?
Сообщение отредактировал kramener - Sep 20 2013, 11:48
|
|
|
|
|
Sep 20 2013, 13:46
|
Группа: Новичок
Сообщений: 2
Регистрация: 12-09-13
Пользователь №: 78 288

|
Только что сам разобрался с uIP  ) Выложу код на всякий случай. Вдруг кому пригодится. Разрабатываю на Stellaris DK-LM3S9D96. uIP 1.0 Инициализация: Код void udp_init() { struct uip_udp_conn *udp_conn; udp_conn = uip_udp_new(0, 0); if (udp_conn == 0) return;
udp_conn->appstate = 0; uip_udp_bind(udp_conn, HTONS(DEFAULT_UDP_PORT)); } Callback. process_msg записывает в структуру outputMsg содержимое и выходной размер outputLen Код void udp_appcall(void) { if (uip_newdata()) { if (uip_udp_conn->lport == HTONS(DEFAULT_UDP_PORT)) { static struct uip_udpip_hdr *hdr; hdr = (struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]; uip_ipaddr_copy(&uip_udp_conn->ripaddr, hdr->srcipaddr); uip_udp_conn->rport = hdr->srcport; inputLen = bMIN(uip_datalen(), sizeof(tRawUdpMessage)); memcpy((char *)&inMsg, (char *)uip_appdata, inputLen); process_msg(&inMsg, &inputLen, &outMsg, &outputLen); memcpy((char *)uip_appdata(), (char *)&outMsg, outputLen); uip_slen = outputLen; uip_process(UIP_UDP_SEND_CONN); } } } P.S: Просьба модераторам объединить 2 сообщения. Цитата(ElectronicsLab @ Aug 20 2013, 14:31)  А как сделать так, чтобы независимо слать данные с МК на комп? Чтобы через WireShark видеть что что-то шлется..? Юзайте uip_poll(). Вот что по этому поводу говорит мануал: http://www.gaisler.com/doc/net/uip-0.9/doc/html/main.htmlЦитата The polling event has two purposes. The first is to let the application periodically know that a connection is idle, which allows the application to close connections that have been idle for too long. The other purpose is to let the application send new data that has been produced. The application can only send data when invoked by uIP, and therefore the poll event is the only way to send data on an otherwise idle connection.
Сообщение отредактировал kramener - Sep 20 2013, 13:49
|
|
|
|
|
Apr 7 2014, 05:47
|
Группа: Новичок
Сообщений: 6
Регистрация: 14-12-13
Пользователь №: 79 623

|
Мне бы вернутся к теме о двух серваках на uIP. Делаю всё как в посте Цырена. Но в результате получаю ошибку "Error[Pe070]: incomplete type is not allowed" в строке struct httpd_state uip_tcp_http;. При этом typedef struct httpd_state uip_tcp_appstate_t; компилируется без проблем. Что я сделал не так? Код #ifndef __MULTIAPPLICATION_H__ #define __MULTIAPPLICATION_H__
#include "webserver.h" #include "telnetd.h"
extern void application(void);
typedef union{ struct telnetd_state uip_tcp_telnet; struct httpd_state uip_tcp_http; } uip_tcp_appstate_t;
//typedef struct httpd_state uip_tcp_appstate_t;
#ifndef UIP_APPCALL #define UIP_APPCALL application #endif
#endif
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|