我正在一个嵌入式系统上工作,如果设备无法建立通信,则会在其中保存数据包。我有很多可以保存数据包的方案,但我想避免保存重复的软件包。
系统的数据包长16个字节,我将它们存储在320个字节的缓冲区中(以便最多保留20个数据包)。
如何检查要保存的数据包是否在缓冲区的某处重复?
答案 0 :(得分:0)
只需循环浏览已保存的数据包,然后将其与要添加的新数据包进行比较
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
// represents a 16 char packet
typedef char packet_t[16];
/* pktbuf library - used to store up to 20 packet_t packets */
struct pktbuf_s {
packet_t buffer[20];
size_t packetcnt;
};
#define PKTBUF_INIT() {0}
int pktbuf_save(struct pktbuf_s *t, packet_t *packet)
{
assert(t != NULL);
assert(packet != NULL);
for (size_t i = 0; i < t->packetcnt; ++i) {
if (!memcmp(&t->buffer[i], packet, sizeof(*packet))) {
// duplicate packet found in buffer, notify user application
return 1;
}
}
if (t->packetcnt == sizeof(t->buffer)/sizeof(*t->buffer)) {
// no place in buffer, notify user
return -1;
}
// save the packet and increment packet count
memcpy(&t->buffer[t->packetcnt], packet, sizeof(*packet));
t->packetcnt++;
// succcess
return 0;
}
void pktbuf_clear(struct pktbuf_s *t)
{
assert(t != NULL);
t->packetcnt = 0;
}
size_t pktbuf_get(struct pktbuf_s *t, packet_t **packets)
{
assert(t != NULL);
*packets = t->buffer;
return t->packetcnt;
}
/* User application example ----------------------------------- */
void packet_receive(packet_t *packet)
{
memset(packet, 1, sizeof(*packet));
}
int main()
{
struct pktbuf_s pktbuf = PKTBUF_INIT();
// some user app receives packet
packet_t packet;
packet_receive(&packet);
// save received packet in bnuffer
if (pktbuf_save(&pktbuf, &packet) == -1) {
// no place in buffer to save the packet
// print error message? blink with the led? or just ignore?
}
// continue the user application, until we want to...
// drain packet buffer
packet_t *packets;
const size_t packetscnt = pktbuf_get(&pktbuf, &packets);
for (size_t i = 0; i < packetscnt; ++i) {
// do smth with packet: packets[i]
}
// clear buffered packets
pktbuf_clear(&pktbuf);
// continue with user application
return 0;
}
答案 1 :(得分:0)
在不知道数据包结构或预期目的的情况下很难给出相关建议。例如,这是RS485网络吗?与单个设备进行UART通信?还有吗?
但是,如果您可以控制数据包的结构,则可以使用数据包标识符或序列号。如果仅与一台设备通信,则仅此一项就足以区分数据包。数据包结构可能类似于以下内容。此处的相关字段是 seq no。(序列号)。数字表示字节偏移。
0 1 2 3 15
---------------------------------------------------
| control | seq no. | len | data | checksum / crc |
---------------------------------------------------
^^^^^^^^^
如果有多个设备,则您的数据包可能包含源和地址字段。在这种情况下,地址信息和数据包标识符的组合就足够了。
0 1 2 3 4 5 15
---------------------------------------------------------------------
| control | seq no. | source | dest | len | data | checksum / crc |
---------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^
将在生成数据包的设备上承担责任,以增加每个新数据包的序号。由于您的缓冲区只能容纳20个数据包,因此1字节的ID /序列字段可能就足够了。
(序列号也可以用于其他目的,例如检查数据包是否在传输过程中丢失-在这种情况下,接收到的数据包的序列号中会有一个“空白”。)
很难知道这种优化是否必要-或使用简单的memcmp()
比较数据包是否足够。