uint64_t
这是uint64在<stdint.h>(/usr/include/stdint.h)中的定义
/* Unsigned. */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
uint64_t在64位环境中表示unsigned long int,无符号长整型。
u表示unsigned,64、32、16、8表示位数,其中uint8_t比较特殊,虽然写了int,但是uint8_t表示的是无符号char(一个char在内存中占用1字节,即8位)
用uint64_t来表示IP+Port
在一些场景中,需要对IP+Port表示的一个节点进行判重,即全局的IP+Port要保持唯一,可以通过位运算将IP+Port转为uint64_t格式并存储。
将IP和Port转为uint64_t
uint64_t HostToUint(const char *ip, uint16_t port){
in_addr_t addr = inet_addr(ip); //typedef uint32_t in_addr_t;
uint64_t res = 0;
//通过位运算将IP和Port拼接成一个uint64_t
res = ((uint64_t)addr << 16) | (uint64_t)(port);
return res; //res即为uint64_t格式的IP+Port
}
通过man命令查看inet_addr
man inet_addr
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
/**
The inet_addr() function converts the Internet host address cp from IPv4
numbers-and-dots notation into binary data in network byte order.
If the input is invalid, INADDR_NONE (usually -1) is returned.
Use of this function is problematic because -1 is a valid address (255.255.255.255).
Avoid its use in favor of inet_aton(), inet_pton(3), or getaddrinfo(3)
which provide a cleaner way to indicate error return.
**/
即inet_addr()可以将IPv4数字和点格式的地址转换成网络字节序。
将uint64_t转为IP和Port
同样的,再对uint64_t的值进行位运算,可以拆分出ip和port
int Uint64ToHost(uint64_t src, uint16_t *port, char* dstIP, size_t desIPsz){
uint32_t ip = (uint32_t)((src & 0xffffffffffff0000u) >> 16);
uint16_t tmpPort = (uint16_t)(src & 0x000000000000ffffu);
*port = (tmpPort);
if(inet_ntop(AF_INET, &ip, dstIP, desIPsz) == NULL){
return -1;
}else{
return 0;
}
}
同样可以用man inet_ntop来查看inet_ntop的帮助信息
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
完整测试代码如下:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <cstdint>
using namespace std;
uint64_t HostToUint(const char *ip, uint16_t port){
in_addr_t addr = inet_addr(ip); //typedef uint32_t in_addr_t;
uint64_t res = 0;
res = ((uint64_t)addr << 16) | (uint64_t)(port);
return res;
}
int Uint64ToHost(uint64_t src, uint16_t *port, char* dstIP, size_t desIPsz){
uint32_t ip = (uint32_t)((src & 0xffffffffffff0000u) >> 16);
uint16_t tmpPort = (uint16_t)(src & 0x000000000000ffffu);
*port = (tmpPort);
if(inet_ntop(AF_INET, &ip, dstIP, desIPsz) == NULL){
return -1;
}else{
return 0;
}
}
int main(int argc, char** agrv){
const char ip[] = "192.168.11.234";
uint16_t port = 12134;
uint64_t res = HostToUint(ip, port);
cout << res << endl;
//res = 257335796707174
char dstIP[17] = "";
uint16_t dstPort = 0;
Uint64ToHost(res, &dstPort, dstIP, sizeof(dstIP));
cout << dstIP << ":" << dstPort << endl;
return 0;
}
运行结果:
257335796707174即192.168.11.234:12134的uint64_t表示形式