Как сделать нисходящее соединение в Contiki-NG с UDP

Я пытаюсь сделать простое сетевое соединение, используя 6LoWPAN с Contiki.

Для простоты я делаю это в Cooja, поэтому я думаю, что аппаратное обеспечение не является ограничением в этой проблеме.

Моя цель - иметь один корень (UDP-сервер) и много узлов (UDP-клиент). С примерами, предоставленными Contiki, я могу начать общение с Мотами и поговорить с Сервером, но возможно ли сделать это наоборот?

Я хочу, чтобы Root начал отправлять сообщение любому клиенту и, если это необходимо, пересылал сообщение через других клиентов в сети.

У вас есть идеи, возможно ли это сделать? Или любой трек для достижения этого?

Обновление: что я пробовал до сих пор:

Что я пробовал до сих пор, на серверном устройстве создайте два процесса, один для инициации рута, а другой для периодической отправки пакета:

      #include "contiki.h"
#include <stdlib.h>
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"
#include "sys/log.h"

#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG

#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678

#define SEND_INTERVAL         (5 * CLOCK_SECOND)

static struct simple_udp_connection udp_conn;
static struct etimer periodic_timer;

PROCESS(udp_server_process, "UDP server");
PROCESS(send_msg_process, "UDP server");
AUTOSTART_PROCESSES(&udp_server_process, &send_msg_process);


static void
udp_rx_callback(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
  LOG_INFO("Received response '%.*s' from ", datalen, (char *) data);
  LOG_INFO_6ADDR(sender_addr);
  LOG_INFO_("\n");
}




PROCESS_THREAD(udp_server_process, ev, data)
{
  PROCESS_BEGIN();

  /* Initialize DAG root */
  NETSTACK_ROUTING.root_start();

  /* Initialize UDP connection */
  simple_udp_register(&udp_conn, UDP_SERVER_PORT, NULL,
                      UDP_CLIENT_PORT, udp_rx_callback);

  PROCESS_END();
}


PROCESS_THREAD(send_msg_process, ev, data)
{
  
  static unsigned count;
  static char str[32];
  uip_ipaddr_t dest_ipaddr;
  LOG_INFO("%u", count);
  PROCESS_BEGIN();

  while(1) {
      etimer_set(&periodic_timer, CLOCK_SECOND);
      PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
        uip_ip6addr(&dest_ipaddr,0xfe80,0,0,0,0x207,0x7,0x7,0x7);
        LOG_INFO("Sending request %u to ", count);
        LOG_INFO_6ADDR(&dest_ipaddr);
        LOG_INFO_("\n");
        snprintf(str, sizeof(str), "hello %d", count);
        simple_udp_sendto(&udp_conn, str, strlen(str), &dest_ipaddr);
        count++;
  }
  PROCESS_END();
}

На стороне клиента код основан просто на прослушивании UDP-сокета и ответе в случае получения пакета.

      #include "contiki.h"
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"

#include "sys/log.h"
#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG

#define WITH_SERVER_REPLY  1
#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678

#define SEND_INTERVAL         (5 * CLOCK_SECOND)

static struct simple_udp_connection udp_conn;

/*---------------------------------------------------------------------------*/
PROCESS(udp_client_process, "UDP client");
AUTOSTART_PROCESSES(&udp_client_process);
/*---------------------------------------------------------------------------*/
static void
udp_rx_callback(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{

  LOG_INFO("Received request '%.*s' from ", datalen, (char *) data);
  LOG_INFO_6ADDR(sender_addr);

  LOG_INFO("Sending response.\n");
  simple_udp_sendto(&udp_conn, data, datalen, sender_addr);

  LOG_INFO_("\n");

}

PROCESS_THREAD(udp_client_process, ev, data)
{
  PROCESS_BEGIN();
  simple_udp_register(&udp_conn, UDP_CLIENT_PORT, NULL,
                      UDP_SERVER_PORT, udp_rx_callback);
  PROCESS_END();
}

Как видите, код для сервера периодически отправляет пакет в направлении ipv6: 0xfe80:0:0:0:0x207:0x7:0x7:0x7, который является ip, который будет назначен моту в cooja, когда он это число 7 в моделировании.

Результаты, которые я получил, заключаются в том, что когда корень (A) и клиент (B) находятся в прямом соединении, они отлично разговаривают друг с другом, но когда я разделяю их и пытаюсь установить соединение из корня (A) клиенту (B) через другого клиента (C), сообщение не дойдет от A до B.

1 ответ

Да, это возможно. Протокол маршрутизации RPL позволяет отправлять пакеты в обоих направлениях от корня и к нему. Просто используйте IP-адрес узла в качестве пункта назначения.

Одна проблема заключается в том, что узел обычно имеет два адреса IPv6:

  • Адреса, начинающиеся с 0xfe80являются локальными ссылками.
  • Адреса, начинающиеся с префикса сети, определяются в конфигурации ОС как UIP_DS6_DEFAULT_PREFIX, равно 0xfd00по умолчанию. Этот адрес присутствует только после того, как узел присоединился к сети RPL.

Пакеты на локальные адреса должны быть односкачковыми, они не пересылаются узлами. Чтобы правильно использовать переадресацию многосегментной сетки, используйте другой адрес в качестве пункта назначения.

Другие вопросы по тегам