реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как правильно использовать LwIP UDP?
misyachniy
сообщение Aug 19 2013, 16:22
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 716
Регистрация: 27-05-05
Из: Kyiv
Пользователь №: 5 454



Поискал оффлайн описание LwIP, есть авторское описение 2001 года.
В онлайне описания функций и структур.

Посмотрел пример UDP от STM
Внем регистрируюи функцию обратного вызова udp_server_callback
Код
   struct udp_pcb *upcb;                                
  
   /* Create a new UDP control block  */
   upcb = udp_new();
  
   /* Bind the upcb to the UDP_PORT port */
   /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
   udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
  
   /* Set a receive callback for the upcb */
   [b]udp_recv(upcb, udp_server_callback, NULL);[/b]


В примере Telnet, на сколько я понял, идет привязка к общей функции tcp

Код
// Initialize the application to listen on the telnet port.
    pcb = tcp_new();
    tcp_bind(pcb, IP_ADDR_ANY, TELNET_PORT);
    pcb = tcp_listen(pcb);
    tcp_accept(pcb, TelnetAccept);



Как правильно присоединиться к стеку, чтобы можно было обновлять реализацию LwIP без больших переделок?
И где почитать толковый "Курс молодого бойца по LwIP"?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 19 2013, 17:39
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



я так понимаю тут
http://lwip.wikia.com/wiki/LwIP_Wiki
там много разных статеек, какие то не дописаны, какие то очень короткие

http://lwip.wikia.com/wiki/Raw/TCP
но лучше я думаю хрен что найдешь, только примеры ковырять...

в целом УДП он как ТСР, только калбека на конект нету, потому что в удп как токового конекта нет.
Go to the top of the page
 
+Quote Post
Alex11
сообщение Aug 19 2013, 20:37
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



У меня примерно так:
Код
    lwip_init();

    //add dm9000 interface

    if(netif_add(&dm9000_if, &ipaddr, &netmask, &gw, NULL, dm9000_init, ip_input) != NULL)
    {
        netif_set_default(&dm9000_if);
        netif_set_up(&dm9000_if); // new step from lwip 1.0.0

        pcbc = udp_new();
        udp_pcbs = pcbc;
        pcbd = udp_new();
        pcbc->next = pcbd;
        udp_recv(pcbc, rcv_pcbc, NULL);
        udp_bind(pcbc, &ipaddr, CMDPORT);
        udp_recv(pcbd, rcv_pcbd, NULL);
        udp_bind(pcbd, &ipaddr, DATAPORT);
    }

- задаются callback для двух портов для работы по UDP
При необходимости можно использовать
Код
    udp_connect(pcbd, &connIP, DATAPORT);

это позволяет отвечать по указанному порту только на запросы от конкретного IP вплоть до udp_disconnect.
Иначе приходят пакеты с любых адресов.
Там, вроде, есть более высокоуровневые команды, но у меня стояла задача укромсать стек до минимального размера, так что я там все поубивал.
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 20 2013, 06:06
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Вот самодельный клиент SNTP:
CODE
/**
* @file sntp.c
* @brief SNTP client / clock
*/

#include "sntp.h"
#include "clock.h"
#include "stm32eth.h"
#include "lwip/udp.h"
#include "lwip/def.h"
#include "myassert.h"

#define SENDFAIL_TIMEOUT 5000 /* 5 seconds */
#define SENT_TIMEOUT 60000 /* 1 minute */
#define BADREPLY_TIMEOUT 60000 /* 1 minute */
#define VALID_TIMEOUT (8 * 3600000) /* 8 hours */

struct sntp_packet
{
uint8_t status;
uint8_t stratum;
uint8_t ppoll;
uint8_t precision;
uint32_t distance;
uint32_t dispersion;
uint32_t refid;
uint64_t reftime;
uint64_t org;
uint64_t rec;
uint64_t xmt;
};

static unsigned int last_time, timeout;
static struct udp_pcb* upcb;
static struct ip_addr server;
static int port = 123;

static uint64_t
ntohll(uint64_t x)
{
#if BYTE_ORDER == BIG_ENDIAN
return x;
#elif BYTE_ORDER == LITTLE_ENDIAN
return ((uint64_t)ntohl((uint32_t)x) << 32) | ntohl((uint32_t)(x >> 32));
#else
#error "Bad BYTE_ORDER"
#endif
}

static void recv(void *arg,
struct udp_pcb *upcb,
struct pbuf *p,
struct ip_addr *addr,
u16_t port)
{
if (p->len == sizeof(struct sntp_packet))
{
int i;
struct sntp_packet aligned;
myassert(p->len == p->tot_len); /* don't accept chained pbuf */
memcpy(&aligned, p->payload, sizeof(aligned));
i = (aligned.status >> 3) & 7;
if ((i < 1) || (i > 4)) /* SNTP version 1..4 */
{
goto out;
}
i = aligned.status & 7;
if ((i != 4) && (i != 5)) /* mode 4 or 5: server or broadcast */
{
goto out;
}
if (aligned.xmt == 0)
{
goto out;
}
clock_settime(ntohll(aligned.xmt));
timeout = VALID_TIMEOUT;
last_time = clock_uptime_ms();
}
out:
pbuf_free(p);
}

void
sntp_enable(bool enable)
{
if (enable)
{
if (upcb == 0)
{
err_t ret;
upcb = udp_new();
myassert(upcb != 0);
ret = udp_bind(upcb, IP_ADDR_ANY, port);
if (ret != ERR_OK)
{
udp_remove(upcb);
upcb = 0;
}
else
{
udp_recv(upcb, recv, 0);
}
timeout = 0;
}
}
else if (upcb != 0)
{
udp_remove(upcb);
upcb = 0;
}
}

bool
sntp_isenabled(void)
{
return upcb != 0;
}

void
sntp_setserveraddr(const struct ip_addr *addr)
{
ip_addr_copy(server, *addr);
}

void
sntp_getserveraddr(struct ip_addr *addr)
{
ip_addr_copy(*addr, server);
}

void
sntp_setserverport(int port_arg)
{
port = port_arg;
if (sntp_isenabled())
{
sntp_enable(false);
sntp_enable(true);
}
}

int
sntp_getserverport(void)
{
return port;
}

static void
send_request(void)
{
struct sntp_packet packet;
struct pbuf* psend;
memset(&packet, 0, sizeof(packet));
packet.status = (3 << 3) /* SNTP vesion 3 */
| (3 << 0); /* Mode: client */
psend = pbuf_alloc(PBUF_RAW, sizeof(packet), PBUF_REF);
if (psend != 0)
{
psend->payload = &packet;
timeout = (udp_sendto(upcb, psend, &server, port) == ERR_OK)
? SENT_TIMEOUT : SENDFAIL_TIMEOUT;
pbuf_free(psend);
}
}

void
sntp_poll(void)
{
static unsigned int link_time;
static bool link = false;
unsigned int now = clock_uptime_ms();
if (stm32eth_link() == false)
{
link_time = now;
}
else if (!link && (now - link_time) > 2000)
{
link = true;
}
if (now - last_time >= timeout)
{
if (link && upcb)
{
send_request();
last_time = now;
}
else
{
last_time = now;
timeout = SENDFAIL_TIMEOUT;
}
}
}
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Aug 21 2013, 10:03
Сообщение #5


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(misyachniy @ Aug 19 2013, 20:22) *
...Как правильно присоединиться к стеку, чтобы можно было обновлять реализацию LwIP без больших переделок?...


самое правильное - почитать соответствующий RFC документ (номера сейчас уже не помню - поищите, уже всё придумано до нас давно). интерфейс от стэка к пользователю определён и описан(какой должен быть). Это если по уму и универсально. Но спускаясь на землю - лучше думаю отталкиваться от существующих известных реализация в конкретных библиотеках. Да и не зачем по большому счёту делать универсализм. Вы будете отдавать на сторону реализацию стэка(ту или иную библиотеку, либо самописание) или юзанье его (типа на аутсорс потроха вашего девайса)?
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 18:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01361 секунд с 7
ELECTRONIX ©2004-2016