C / Cygwin:将htoll()从macOS / unix移植到Windows Cygwin

时间:2016-11-28 15:22:48

标签: c windows unix networking cygwin

我正在将我的应用程序从macOS平台转移到Windows平台(这里是Cygwin)。我遇到网络函数ntohll()和htonll()的问题,而ntohl()/ htonl()和ntohs()/ htons()似乎工作正常

    /* LACK OF ntohll() function definition on Cygwin */
    // convert int64 from network to host representation
    *int64 = ntohll(network_int64);

    /* SEEMS TO WORK CORRECTLY */
    // convert int32 from network to host representation
    *int32 = ntohl(network_int32);

更新:这个怎么样?

uint64_t ntohll(uint64_t network_num64) {

    uint32_t network_num32[2];
    uint32_t host_num32[2];
    uint64_t host_num64;

    memcpy(network_num32, &network_num64, sizeof(network_num64));
    host_num32[0] = ntohl(network_num32[0]);
    host_num32[1] = ntohl(network_num32[1]);

    memcpy(&host_num64, host_num32, sizeof(host_num64));
    return host_num64;
}

uint64_t htonll(uint64_t host_num64) {

    uint32_t host_num32[2];
    uint32_t network_num32[2];
    uint64_t network_num64;

    memcpy(host_num32, &host_num64, sizeof(host_num64));
    network_num32[0] = htonl(host_num32[0]);
    network_num32[1] = htonl(host_num32[1]);

    memcpy(&network_num64, network_num32, sizeof(network_num64));
    return network_num64;
}

1 个答案:

答案 0 :(得分:0)

我编写了自己的htonll()和ntohll()函数,可以在uint64_t(64位数字)的情况下解决Cygwin上的字节序问题。我认为它应该有效,但也希望你证明它确实是一个很好的解决方案。

我写了以下功能: 1. isBigEndian()和isLittleEndian() - 检查当前主机是使用大端还是小端 2.我认为Network Byte Order是Big Endian。因此,如果在当前主机上有Little Endian,我将需要交换字节序,如果Big Endian比我刚才可以使用在hto​​nll()/ ntohll()param的数字中收到的字节序。 3.我编写的函数可以将字节顺序从大或小转换为小容量或大容量转换为64位数字,即swapEndianness()

以下是所有代码:

bool isBigEndian() {
    int n = 1;
    // little endian if true
    if(*(char *)&n == 1) {
        return false;
    }
    return true;
}

bool isLittleEndian() {
    return  !(isBigEndian());
}

uint64_t swapEndianness(uint64_t num) {

    uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
    uint64_t swapped_num;

    b0 = (num & 0x00000000000000ff) << 56u;
    b1 = (num & 0x000000000000ff00) << 40u;
    b2 = (num & 0x0000000000ff0000) << 24u;
    b3 = (num & 0x00000000ff000000) << 8u;
    b4 = (num & 0x000000ff00000000) >> 8u;
    b5 = (num & 0x0000ff0000000000) >> 24u;
    b6 = (num & 0x00ff000000000000) >> 40u;
    b7 = (num & 0xff00000000000000) >> 56u;

    swapped_num = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7; 

    return swapped_num;
}

uint64_t htonll(uint64_t host_num64) {

    if(isLittleEndian()) {
        // swap little endian to big endian (network byte order)
        return swapEndianness(host_num64);
    }
    return host_num64;
}

uint64_t ntohll(uint64_t network_num64) {

    if(isLittleEndian()) {
        // swap big endian (network byte order) to little endian
        return swapEndianness(network_num64);
    }
    return network_num64;
} 

我还测试了以上代码:

static void test_swap_endianness(void) {

    uint64_t number = 0x1123456789ABCDEF;
    printf("hex number = 0x%" PRIx64 "\n", number);

    uint64_t swappedNumber = swapEndianness(number);
    printf("hex swapped number: 0x%" PRIx64 "\n", swappedNumber);
}

并在交换uint64_t数字的字节顺序时实现正确的输出:

=========== test_swap_endianness ==============
hex number = 0x1123456789abcdef
hex swapped number: 0xefcdab8967452311