0

我刚开始学习套接字编程,我正在尝试使用原始套接字实现 TCP/UDP 协议。

    IP Header
    0      7 8     15 16    23 24    31
    +--------+--------+--------+--------+
    |Ver.|IHL|DSCP|ECN|   Total length  |
    +--------+--------+--------+--------+
    |  Identification |Flags|   Offset  |
    +--------+--------+--------+--------+
    |   TTL  |Protocol| Header Checksum |
    +--------+--------+--------+--------+
    |         Source IP address         |
    +--------+--------+--------+--------+
    |       Destination IP address      |
    +--------+--------+--------+--------+

写IP头、Flags和Offset部分时,Offset的长度不是8位的倍数。所以我把Flags和Offset作为一个整体。

uint8 flags = 0;
uint16 offset = htons(6000); // more than 1 byte, so we need to use htons

// in c, we can left(since it's in big endianness) shift offset 3 bit, 
// and then convert flags to uint16, and then merge them together

// in some other languages, for example, Haskell, 
// htons like functions may return a bytestring which is not an instance of Bit, 
// we need to unpack it back into a list of uint8 in order to use bitwise operations.

这种方法不是很干净,我想知道当它的组件长度超过 1 个字节并且还需要考虑它们的字节顺序时,构造字节串的常用方法是什么。

4

1 回答 1

0

在 C 中,通常的方法是声明一个uint16_tuint32_tuint64_t临时变量,使用按位运算符来组装该变量中的位,然后使用htons()htonl()将这些位转换为网络(又名大端)顺序。

例如,FlagsOffset字段一起构成一个 16 位字。所以:

uint8_t flags   = /* some 3-bit value */;
uint16_t offset = /* some 13-bit value */;
uint16_t flagsAndOffsetBigEndian = htons(flags | (offset << 3));
memcpy(&header[16], &flagsAndOffsetBigEndian, sizeof(uint16_t));
于 2019-11-02T13:24:52.490 回答