[英]how can I avoid padding in sending the packet
我想使用 write 系統調用發送一個數據包。 我創建了數據包,它的大小是 46 字節。 當我在wireshark的程序中發送數據包時,長度為60字節,填充14字節。 如何在沒有填充的情況下發送數據包。
我不能使用套接字命令。
struct x {
bool is_active;
bool is_owner;
int fd1;
int fd2;
char pkt_hdr[sizeof(struct ether_header) + sizeof(struct ip)];
struct interface *ifp;
int fd_bufflen;
struct ipaddr src;
uint8_t ibuf[IP_MAXPACKET];
int family;
struct vrrp_vrouter *vr;
struct list *addrs;
bool ad;
bool ga;
bool nd;
uint8_t priority;
uint16_t ma_val;
uint16_t sk_tm;
uint16_t ma_val;
struct ethaddr vmac;
struct {
int state;
} fsm;
struct {
uint32_t ad_cnt;
uint32_t ar_cnt;
uint32_t g_cnt;
uint32_t un_cnt;
uint32_t t_cnt;
} stats;
struct thread *t_ti;
struct thread *t_adti;
struct thread *t_read;
struct thread *t_write;
};
.
.
.
size_t buf_len = pktsz + sizeof r->pkt_hdr;
.
.
.
/* Ethernet Header */
struct ether_header *ether_hdr = (struct ether_header *)buf;
.
.
.
/* IP Header */
struct ip *ip_hdr = (struct ip *) (ether_hdr + 1);
ip_hdr->ip_len = htons(buf_len - sizeof(struct ether_header));
ip_hdr->ip_src = r->src.ipaddr_v4;
ip_hdr->ip_sum = in_cksum(ip_hdr, sizeof(struct ip));
/* Payload */
memcpy((void *)(buf + sizeof r->pkt_hdr), (const void *)pkt, pktsz);
ssize_t sent = write(fd, buf, buf_len);
free(buf);
buf_len 是:46
pktsz : 12
r->pkt_hdr 的大小:34
長度為 46。
不幸的是, struct
在存儲協議方面通常非常糟糕,因為它們的對齊和填充要求。 這意味着您不能在整個結構上使用memcpy
等。 相反,必須在通過數據通信協議發送之前對struct
進行序列化,以丟棄填充。
簡化示例:
typedef struct
{
int i;
char c;
} foo_t;
void foo_serialize (uint8_t dst[5], const foo_t* src)
{
memcpy(dst, &src->i, 4);
dst[4] = src->c;
}
在接收端需要一個類似的反序列化程序。
另一種選擇是使用非標准的#pragma pack(1)
和類似方法“打包”結構。 這消除了填充,但填充是有原因的。 如果打包結構體,您的程序最終可能會讀取它未對齊,這可能導致代碼變慢或某些系統硬件異常。
但同時您還需要轉換為網絡字節序。 Big endian 通常用於大多數數據協議。 重寫上面的例子,也可以從 little endian 轉換為 big endian:
void foo_serialize (uint8_t dst[5], const foo_t* src)
{
dst[0] = ((uint32_t)src->i >> 24) & 0xFFu;
dst[1] = ((uint32_t)src->i >> 16) & 0xFFu;
dst[2] = ((uint32_t)src->i >> 8) & 0xFFu;
dst[3] = ((uint32_t)src->i >> 0) & 0xFFu;
dst[4] = src->c;
}
還有 POSIX htonl
函數(主機字節序到網絡字節序,長格式),但由於該函數不能在 POSIX PC 計算機之外移植,它有點違背了它自己的目的。
打包可防止編譯器進行填充 - 這必須明確要求 - 在 GCC 下使用__attribute__((__packed__)) 。
有關更多解釋,請訪問以下鏈接: https : //www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.