evgeniy1294 (04.04.2019 11:03, просмотров: 200) ответил GF6 на Скинте, пожалуйста.
Там скидывать особо нечего: 1) Вначале создаем protocol control block
err_t lwip_error = ERR_OK;
// Create new PCB (Protocol Control Block)
pcb = udp_new();
if (pcb)
{
lwip_error = udp_bind(pcb, IP4_ADDR_ANY, local_port);
if (lwip_error == ERR_OK)
{
udp_recv(pcb, callback::recvData, (void*)this);
state = state_t::wait; // ждем коннекта
}
else
error = error_t::bind;
}
else
error = error_t::init;
2) Код самого колбэка, который будет вызван по приёму пакета. В качестве arg использую указатель на класс-обработчик
void recvData(void* arg, struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr, u16_t remote_port)
{
socket* instance = (socket*)arg;
instance->recvCbkHandler(arg, pcb, p, addr, remote_port); // Вызываем обработчик для конкретного экземпляра класса
return;
}
3) Код обработчика в классе.
void socket::recvCbkHandler(void* arg, udp_pcb* upcb, pbuf* p, const ip_addr_t* remote_ip, uint16_t remote_port)
{
if (p == nullptr) return;
// Тут я проверяю буфер на наличие необработанных пакетов.
if (rlen != 0){pbuf_free(p); return;}
// Входящий пакет может быть больше размера буфера.
if (rbuf->len < p->len){pbuf_free(p); return;}
// Копирую пакет в буфер
memcpy(rbuf->payload, p->payload, p->len); rlen = p->len;
// Запоминаю, откуда прилетел пакет
pcb->remote_ip = *remote_ip;
pcb->remote_port = remote_port;
// Освобождаю буфер
pbuf_free(p);
return;
}
4) Запись данных в udp-сокет.
auto socket::write(uint8_t* pdata, uint16_t size) -> error_t
{
if (size == 0) return error_t::parameter;
pbuf* p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
if (p == nullptr) return error_t::bad_alloc;
memcpy(p->payload, pdata, size);
udp_send(pcb, p);
pbuf_free(p);
return error_t::ok;
}
Все, больше ничего особого нет. Только внутренняя логика.