Top.Mail.Ru

STM32 и Ethernet. Часть 5. Транспортный уровень. Протокол UDP.

Нежданно-негаданно, благодаря теме на форуме, произошел возврат к одной из предыдущих тем, а именно к связке STM32 и ENC28J60 и Ethernet. И в этой, пятой, части обработаем принятый UDP-пакет и отправим на него ответ. Причем в отличие от предыдущих частей я не буду делать обширную врезку с теорией касаемо UDP, может быть потом, в отдельной статье, но вряд ли ) Просто и кратко дополним созданный ранее проект необходимым функционалом и посмотрим на результат.

Но для начала освежим в памяти предыдущие части:

Итак, протокол UDP относится к транспортному уровню, а значит мы снова движемся вверх по модели OSI:

UDP протокол

Отличительной особенностью UDP является то, что для обмена сообщениями-датаграммами устройствам не требуется никакой предварительной подготовки. То есть никаких установок соединений, рукопожатий, открытия каналов связи и тому подобного. Данные могут спокойно потеряться по пути, порядок следования датаграмм может быть нарушен, все это не контролируется. Возникает резонный вопрос - зачем тогда это нужно? А отчет достаточно прост - например, для очень чувствительных ко времени систем, систем реального времени. В таком случае в жертву приносятся дополнительные проверки и контроль, из-за чего и получаем выигрыш во времени. Если потери пакетов, ошибки, дублирования критичны, то тут уже вступает в дело, к примеру, TCP, но сегодня не об этом.

Для обмена данными по UDP необходимо знать ip-адрес и порт участников обмена. Порт представляет из себя целое число от 0 до 65535 (16-ти битное значение). Собственно, в практическом примере увидим этот механизм наглядно.

Каждая датаграмма включает в себя заголовок и непосредственно данные:

UDP frame

Пробежимся по полям заголовка:

  • Source port - порт отправителя
  • Destination port - порт получателя
  • Length - длина датаграммы, причем включает в себя и заголовок и данные(!)
  • Checksum - контрольная сумма

При этом для IPv4 контрольная сумма и порт отправителя являются необязательными полями. Все, что нам потребуется на практике, выяснили, добавляем в проект два новых файла:

  • udp.c
  • udp.h

Первым делом, определим структуру для UDP датаграмм в udp.h, выглядит она следующим образом:

typedef struct UDP_Frame
{
  uint16_t srcPort;
  uint16_t destPort;
  uint16_t len;
  uint16_t checkSum;
  uint8_t data[];
} UDP_Frame;

Прекрасно, здесь же зададим номер порта, который используем для тестирования:

#define UDP_DEMO_PORT                                                   33333

Для примера реализуем простой механизм: инкрементируем все байты в принятой датаграмме и отправим обратно уже измененными. Мате