尝试使用线程和计时器通过 UDP 发送两条不同的消息失败
Failing attempt to use thread and timer to send two different messages with UDP
我想从服务器向客户端发送两种不同类型的消息。我为这两条不同的消息分别创建了两个函数 data_signal()
和 probe_signal()
。
data_signal()
函数会以CLOCK_SECOND * 1
的间隔周期性的向客户端发送定义的消息。
我使用定时器 CLOCK_SECOND * 30
持续时间来定期调用 probe_signal()
向客户端发送不同的消息。
目前 data_signal()
函数正在按预期运行。但是 probe_signal()
函数没有将其消息发送到客户端。
我已经通过简单地在客户端打印消息验证了这一点,但没有收到 "probe_signal()" 消息。
此外,如果我评论 data_signal()
的 uip_udp_packet_send(conn, buf, strlen(buf));
行,那么我就能收到来自 probe_signal()
的消息。我认为发生此问题是因为我使用的是相同的 UDP 连接
代码:
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"
#include <string.h>
#define SERVER_IP "fe80::9a07:2dff:fe3c:8d01" //"::"
#define CLIENT_PORT 61617
#define SERVER_PORT 61616
#define PING_TIMEOUT (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1)
#define UDP_LEN_MAX 255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;
static struct etimer timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;
/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
uint8_t *data, uint16_t datalen)
{
PRINTF("echo response received\n");
echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{
}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{
sprintf(buf, "Current packet count is: %04u!",packet_counter);
PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
uip_udp_packet_send(conn, buf, strlen(buf));
packet_counter++;
}
static void probe_signal(void)
{
sprintf(buf, "%04u", probe_packet_counter);
uip_udp_packet_send(conn, buf, strlen(buf));
printf("Probe signal is sent");
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
static struct timer t;
PROCESS_BEGIN();
PRINTF("CC26XX-IPv6-over-BLE client started\n");
conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
udp_bind(conn, UIP_HTONS(CLIENT_PORT));
timer_set(&t, CLOCK_SECOND * 30);
etimer_set(&timer, CLIENT_SEND_INTERVAL);
while(1)
{
if(timer_expired(&t))
{
flag =1;
if(flag==1)
{
probe_signal();
timer_reset(&t);
printf("Timer is reset\n");
}
}
PROCESS_YIELD();
if((ev == PROCESS_EVENT_TIMER) && (data == &timer))
{
data_signal();
etimer_set(&timer, CLIENT_SEND_INTERVAL);
}
else if(ev == tcpip_event)
{
printf("TCPIP event occured\n");
tcpip_handler();
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
有人可以指导如何解决这个问题,这将是一个很大的帮助。
我可以通过更改代码解决此问题:
- 已将计时器类型更改为
etimer
- 等待
etimer
事件,然后调用 probe_signal()
。
来自 Documentation: Processes and events 的活动和日程安排:
Contiki-NG is built on an event-based execution model, where processes
typically perform chunks of work before telling the scheduler that
they are waiting for an event, and thereby suspend execution. Such
events can be the expiration of a timer, an incoming network packet,
or a serial line message being delivered.
Processes are scheduled cooperatively, which means that each process
is responsible for voluntarily yielding control back to the operating
system without executing for too long. Hence, the application
developer must make sure that long-running operations are split into
multiple process schedulings, allowing such operations to resume at
the point where they last stopped.
并且来自同一文档的暂停和产生部分:
By contrast, PROCESS_YIELD() will yield control back to the scheduler
without expecting to be scheduled again shortly thereafter. Instead,
it will wait for an incoming event, similar to
PROCESS_WAIT_EVENT_UNTIL(), but without a required condition argument.
可以在 Timers in the contiki-os github repository:
找到关于 Etimer 库的讨论
The Contiki etimer library provides a timer mechanism that generate
timed events. An event timer will post the event PROCESS_EVENT_TIMER
to the process that set the timer when the event timer expires. The
etimer library use clock_time() in the clock module to get the current
system time.
更新代码:
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"
#include <string.h>
#define SERVER_IP "fe80::9a07:2dff:fe3c:8d01" //"::"
#define CLIENT_PORT 61617
#define SERVER_PORT 61616
#define PING_TIMEOUT (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1)
#define PROBE_SIGNAL_INTERVAL (CLOCK_SECOND * 30)
#define UDP_LEN_MAX 255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;
static struct etimer timer,probe_timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;
/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
uint8_t *data, uint16_t datalen)
{
PRINTF("echo response received\n");
echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{
}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{
sprintf(buf, "Current packet count is: %04u!",packet_counter);
PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
uip_udp_packet_send(conn, buf, strlen(buf));
packet_counter++;
}
static void probe_signal(void)
{
sprintf(buf, "%04u", probe_packet_counter);
uip_udp_packet_send(conn, buf, strlen(buf));
printf("Probe signal is sent");
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
PROCESS_BEGIN();
PRINTF("CC26XX-IPv6-over-BLE client started\n");
conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
udp_bind(conn, UIP_HTONS(CLIENT_PORT));
etimer_set(&probe_timer, PROBE_SIGNAL_INTERVAL); // set up a timer event for calling probe_signal() function
etimer_set(&timer, CLIENT_SEND_INTERVAL); // set up a timer event for calling data_signal() function
while(1)
{
PROCESS_YIELD(); // yield waiting for an timer event or other event
if((ev == PROCESS_EVENT_TIMER) && (data == &timer))
{
// timer event received so process it and then reschedule again.
data_signal();
etimer_set(&timer, CLIENT_SEND_INTERVAL);
}
if((ev == PROCESS_EVENT_TIMER) && (data == &probe_timer))
{
// timer event received so process it and then reschedule again.
probe_signal();
etimer_set(&timer, PROBE_SIGNAL_INTERVAL);
}
else if(ev == tcpip_event)
{
printf("TCPIP event occured\n");
tcpip_handler();
}
}
PROCESS_END();
}
我想从服务器向客户端发送两种不同类型的消息。我为这两条不同的消息分别创建了两个函数 data_signal()
和 probe_signal()
。
data_signal()
函数会以CLOCK_SECOND * 1
的间隔周期性的向客户端发送定义的消息。
我使用定时器 CLOCK_SECOND * 30
持续时间来定期调用 probe_signal()
向客户端发送不同的消息。
目前 data_signal()
函数正在按预期运行。但是 probe_signal()
函数没有将其消息发送到客户端。
我已经通过简单地在客户端打印消息验证了这一点,但没有收到 "probe_signal()" 消息。
此外,如果我评论 data_signal()
的 uip_udp_packet_send(conn, buf, strlen(buf));
行,那么我就能收到来自 probe_signal()
的消息。我认为发生此问题是因为我使用的是相同的 UDP 连接
代码:
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"
#include <string.h>
#define SERVER_IP "fe80::9a07:2dff:fe3c:8d01" //"::"
#define CLIENT_PORT 61617
#define SERVER_PORT 61616
#define PING_TIMEOUT (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1)
#define UDP_LEN_MAX 255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;
static struct etimer timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;
/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
uint8_t *data, uint16_t datalen)
{
PRINTF("echo response received\n");
echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{
}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{
sprintf(buf, "Current packet count is: %04u!",packet_counter);
PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
uip_udp_packet_send(conn, buf, strlen(buf));
packet_counter++;
}
static void probe_signal(void)
{
sprintf(buf, "%04u", probe_packet_counter);
uip_udp_packet_send(conn, buf, strlen(buf));
printf("Probe signal is sent");
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
static struct timer t;
PROCESS_BEGIN();
PRINTF("CC26XX-IPv6-over-BLE client started\n");
conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
udp_bind(conn, UIP_HTONS(CLIENT_PORT));
timer_set(&t, CLOCK_SECOND * 30);
etimer_set(&timer, CLIENT_SEND_INTERVAL);
while(1)
{
if(timer_expired(&t))
{
flag =1;
if(flag==1)
{
probe_signal();
timer_reset(&t);
printf("Timer is reset\n");
}
}
PROCESS_YIELD();
if((ev == PROCESS_EVENT_TIMER) && (data == &timer))
{
data_signal();
etimer_set(&timer, CLIENT_SEND_INTERVAL);
}
else if(ev == tcpip_event)
{
printf("TCPIP event occured\n");
tcpip_handler();
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
有人可以指导如何解决这个问题,这将是一个很大的帮助。
我可以通过更改代码解决此问题:
- 已将计时器类型更改为
etimer
- 等待
etimer
事件,然后调用probe_signal()
。
来自 Documentation: Processes and events 的活动和日程安排:
Contiki-NG is built on an event-based execution model, where processes typically perform chunks of work before telling the scheduler that they are waiting for an event, and thereby suspend execution. Such events can be the expiration of a timer, an incoming network packet, or a serial line message being delivered.
Processes are scheduled cooperatively, which means that each process is responsible for voluntarily yielding control back to the operating system without executing for too long. Hence, the application developer must make sure that long-running operations are split into multiple process schedulings, allowing such operations to resume at the point where they last stopped.
并且来自同一文档的暂停和产生部分:
By contrast, PROCESS_YIELD() will yield control back to the scheduler without expecting to be scheduled again shortly thereafter. Instead, it will wait for an incoming event, similar to PROCESS_WAIT_EVENT_UNTIL(), but without a required condition argument.
可以在 Timers in the contiki-os github repository:
找到关于 Etimer 库的讨论The Contiki etimer library provides a timer mechanism that generate timed events. An event timer will post the event PROCESS_EVENT_TIMER to the process that set the timer when the event timer expires. The etimer library use clock_time() in the clock module to get the current system time.
更新代码:
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"
#include <string.h>
#define SERVER_IP "fe80::9a07:2dff:fe3c:8d01" //"::"
#define CLIENT_PORT 61617
#define SERVER_PORT 61616
#define PING_TIMEOUT (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1)
#define PROBE_SIGNAL_INTERVAL (CLOCK_SECOND * 30)
#define UDP_LEN_MAX 255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;
static struct etimer timer,probe_timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
static uint16_t probe_packet_counter;
static uint16_t actualSent_packet_counter;
static int flag;
/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
uint8_t *data, uint16_t datalen)
{
PRINTF("echo response received\n");
echo_received = 1;
}
/*---------------------------------------------------------------------------*/
static void tcpip_handler(void)
{
}
/*---------------------------------------------------------------------------*/
static void
data_signal(void)
{
sprintf(buf, "Current packet count is: %04u!",packet_counter);
PRINTF("send message: <%s>\n", buf); /*This printf is commented for understanding the low level code*/
uip_udp_packet_send(conn, buf, strlen(buf));
packet_counter++;
}
static void probe_signal(void)
{
sprintf(buf, "%04u", probe_packet_counter);
uip_udp_packet_send(conn, buf, strlen(buf));
printf("Probe signal is sent");
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
PROCESS_BEGIN();
PRINTF("CC26XX-IPv6-over-BLE client started\n");
conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
udp_bind(conn, UIP_HTONS(CLIENT_PORT));
etimer_set(&probe_timer, PROBE_SIGNAL_INTERVAL); // set up a timer event for calling probe_signal() function
etimer_set(&timer, CLIENT_SEND_INTERVAL); // set up a timer event for calling data_signal() function
while(1)
{
PROCESS_YIELD(); // yield waiting for an timer event or other event
if((ev == PROCESS_EVENT_TIMER) && (data == &timer))
{
// timer event received so process it and then reschedule again.
data_signal();
etimer_set(&timer, CLIENT_SEND_INTERVAL);
}
if((ev == PROCESS_EVENT_TIMER) && (data == &probe_timer))
{
// timer event received so process it and then reschedule again.
probe_signal();
etimer_set(&timer, PROBE_SIGNAL_INTERVAL);
}
else if(ev == tcpip_event)
{
printf("TCPIP event occured\n");
tcpip_handler();
}
}
PROCESS_END();
}