C/C++中网络程序如何传输long long类型和double类型数据

图片来源于网络

背景

在用C/C++写网络程序的传输数值型数据的时候,我们会遇到字节的网络字节序和主机字节序问题,下面先来看一下什么是字节序。
字节序,简单来说就是数据在计算机硬件上的数值存储方式:大端字节序(big endian)和小端字节序(little endian)。
大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
小端字节序:低位字节在前,高位字节在后,即以0x1122形式储存。

在网络编程中,我们把这种本地计算机硬件的数据存储方式又称为主机字节序。
(1)主机字节序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。 如 Intelx86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78
由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序。
(2)网络字节序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。

C/C++基本数据类型及所占的字节数

C/C++下基本数据类型所占的位数与编译器有关。下面给出不同数据类型对应不同编辑器的位数。

数据类型 16位编译器(字节数) 32位编译器(字节数) 64位编译器(字节数)
char 1 1 1
short int 2 2 2
int 2 4 4
unsingned int 2 4 4
float 4 4 4
double 8 8 8
long 4 4 8
unsingned long 4 4 8
long long 8 8 8
void *(指针变量) 2 4 8

网络字节序与本地字节序之间的转换函数

网络字节顺序与本地字节顺序之间的转换函数包含以下四个:

htons 把 unsigned short 类型从主机序转换到网络序;
htonl 把 unsigned long 类型从主机序转换到网络序;
ntohs 把 unsigned short 类型从网络序转换到主机序;
ntohl 把 unsigned long 类型从网络序转换到主机序;

这四个函数的函数声明为:

 uint32_t htonl(uint32_t hostlong);
 uint16_t htons(uint16_t hostshort);
 uint32_t ntohl(uint32_t netlong);
 uint16_t ntohs(uint16_t netshort);

从函数声明我们可以看出转换函数仅支持到32位数据,如何实现64位数据的转换呢?
下面给出我们自己的实现方法:

uint64_t ntohll(uint64_t _netlong)
{
    uint64_t result = ntohl(_netlong);
    return (result << 32 | ntohl(_netlong >> 32));
}

uint64_t htonll(uint64_t _hostlong)
{
    uint64_t result = htonl(_hostlong);
    return (result << 32 | htonl(_hostlong >> 32));
}

double ntoh_double(double _netd)
{
    uint64_t result = ntohll(*((uint64_t *)&_netd));
    return *((double *)&result);
}

double hton_double(double _hostd)
{
    uint64_t result = htonll(*((uint64_t *)&_hostd));
    return *((double *)&result);
}

加上以上四个方法,我们就可以通过传递所有类型的数据了。

你可能感兴趣的:(C/C++中网络程序如何传输long long类型和double类型数据)