所以我试图将结构写入二进制文件。它完美地工作,直到我只编写一部分字节。对于data_offset,reserved和ctl_bit,我只想将最后4,6,6位写入二进制文件。我不确定我哪里出错了。
struct tcp_head
{
unsigned short source_port; //16 bits
unsigned short dest_port; //16 bits
unsigned int seq_num; //32 bits
unsigned int ack_num; //32 bits
unsigned char data_offset; //4 bits
unsigned short reserved; //6 bits
unsigned short ctl_bit; //6 bits
unsigned short window; //16 bits
unsigned short checksum; //16 bits
unsigned short urgent_point; //16 bits
};
当我编写文件时,我试图使用逐位运算符进行混合使用。
FILE *filePtr = fopen(filename, "wb");
int i;
if (!filePtr)
{
printf("\nError while writing file\n");
exit(1);
}
(*temp).data_offset = (*temp).data_offset << 4;
(*temp).reserved = (*temp).reserved << 10;
(*temp).ctl_bit = (*temp).ctl_bit << 10;
fwrite(&(temp->dest_port), sizeof((*temp).dest_port), 1, filePtr);
fwrite(&(temp->source_port), sizeof((*temp).source_port), 1, filePtr);
fwrite(&(temp->seq_num), sizeof((*temp).seq_num), 1, filePtr);
fwrite(&(temp->ack_num), sizeof((*temp).ack_num), 1, filePtr);
fwrite(&(temp->data_offset), sizeof((*temp).data_offset), 1, filePtr);
fwrite(&(temp->reserved),sizeof((*temp).reserved), 1, filePtr);
fwrite(&(temp->ctl_bit), sizeof((*temp).ctl_bit), 1, filePtr);
fwrite(&(temp->window), sizeof((*temp).window), 1, filePtr);
fwrite(&(temp->checksum), sizeof((*temp).checksum), 1, filePtr);
fwrite(&(temp->urgent_point), sizeof((*temp).urgent_point), 1, filePtr);
fclose(filePtr);
答案 0 :(得分:1)
你说:
我只想将最后4,6,6位写入二进制文件。
你的代码确实:
(*temp).data_offset = (*temp).data_offset << 4;
(*temp).reserved = (*temp).reserved << 10;
(*temp).ctl_bit = (*temp).ctl_bit << 10;
(*temp).data_offset << 4;
稍微偏移了4.您需要的是将除最后一个之外的所有位清零。您可以通过使用:
(*temp).data_offset = (*temp).data_offset & 0x0F;
同样,您需要使用:
(*temp).reserved = (*temp).reserved & 0x3F;
(*temp).ctl_bit = (*temp).ctl_bit & 0x3F;
除了最后6位之外,这将把所有位清零。
创建存储转换值并保存转换值的临时变量可能更好。否则,您正在修改对象而无法恢复到原始状态。
答案 1 :(得分:0)
当尝试编写精确的二进制块(如TCP头)时,通常最好先将结构成员复制到缓冲区中,然后再写入缓冲区。这不仅可以让您移动单个位,还可以处理字节序:
// Need htons(), etc.
#include <arpa/inet.h>
// Need uint16_t, etc.
#include <stdint.h>
. . .
unsigned char buf[20];
*(uint16_t *)buf = htons(temp->source_port);
*(uint16_t *)(buf + 2) = htons(temp->dest_port);
*(uint32_t *)(buf + 4) = htonl(temp->seq_num);
*(uint32_t *)(buf + 8) = htonl(temp->ack_num);
*(uint16_t *)(buf + 12) = ((temp->data_offset & 0x0F) << 12) |
((temp->reserved & 0x3F) << 6) |
(temp->ctl_bit & 0x3F);
*(uint16_t *)(buf + 14) = htons(temp->window);
*(uint16_t *)(buf + 16) = htons(temp->checksum);
*(uint16_t *)(buf + 18) = htons(temp->urgent_point);
现在buf
是一个格式正确的网络顺序TCP标头(假设您的结构是“主机”顺序),并且可以写成一个字节块。