通过套接字发送整数,同时避免违反严格的别名规则

问题描述

我正在尝试通过C以网络形式发送一个整数(更具体地说,uint32_t个字节)。我相信我会根据Stack Overflow上的其他示例和答案正确发送数据;但是,在接收字节时,我在不破坏uint32_t的情况下将它们强制转换/转换为strict aliasing rule时遇到了麻烦。这是我最初尝试的一个示例:

发件人:

uint32_t num = htonl(100);
char* converted_num = (char*)#
send(client_sock,converted_num,sizeof(num),0);

接收器:

char buf[8192];
recv(socket,buf,8192,0);
uint32_t test = ntohl(*(uint32_t*)&buf);
printf("%d\n",(int)test);

虽然这似乎可行,但我收到了反馈,uint32_t test = ntohl(*(uint32_t*)&buf);行违反了严格的别名规则。这是我修复严格的别名冲突的尝试:

char buf[8192];
recv(socket,0);
uint32_t test = ntohl(*(uint32_t*)memcpy(&(uint32_t){0},&buf[0],sizeof(uint32_t)));
printf("%d\n",(int)test);

这会导致程序崩溃,即我的问题是,在通过c(Windows)中的套接字传输整数时,如何最有效地避免违反严格的别名规则。

解决方法

您的原始代码在严格的别名上没有任何问题-谁给您反馈是不正确的。 确实存在的问题是对齐方式–没有保证scala> "cat /tmp/data/part-00000-cf540e79-d32e-413f-9d5d-1a08b6eb8d21-c000.txt".! [1,"John",{"F":"John","L":"Smith"}] [2,"Jane",{"F":"Jane","L":"Doe"}] 可以正确对齐char buff[8192];以外的任何类型(尽管可能会)。您可以通过使用malloc分配缓冲区来避免该问题:

char

malloc将始终返回为任何类型适当分配的内存。然后输入您的代码

char *buf = malloc(8192);

是安全的,尽管您应该检查malloc是否成功。

,

只需将其分成几行:

uint32_t tmp;
memcpy(&tmp,buf + whatever,sizeof tmp);
result = ntohl(tmp);

您也可以使其成为内联函数:

static inline uint32_t get_u32(char *from) {
    uint32_t tmp;
    memcpy(&tmp,from,sizeof tmp);
    return ntohl(tmp);
}

...

uint32_t test = get_u32(buf + whatever);
,

使用char代替uint32_t并丢弃所有投射。使用正确的类型打印并使用recv()返回的正确类型。

//char buf[8192];
uint32_t buf[8192/sizeof(uint32_t)];

//recv(socket,buf,8192,0);
ssize_t len = recv(socket,sizeof buf,0);

if (len != -1) { 
  if (len % sizeof *buf != 0) { ; } // TBD code to handle non-multiples of 32-bits
  len /= sizeof *buf;
  for (ssize_t i = 0; i< len; i++) {
    //uint32_t test = ntohl(*(uint32_t*)&buf);
    //printf("%d\n",(int)test);
    printf("%" PRIu32 "\n",buf[i]);
  }
}