做通信相关的业务,经常要与IP字段打交道,不论是CLI下发配置IP,还是消息包中的IP字段,一般配置的话都是字符串,需要对其进行正则校验,消息包流的话都是字节数组,这样就需要字符串与字节数组间进行转化。
正则校验表达式
ipv4
((\s+)|(\.{0})|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))
ipv6
((\s+)|(\.{0})|(([0-9A-Fa-f]{1,4}):){7}([0-9A-Fa-f]{1,4}))
这个IPV6的缺点就是强制需要7个冒号,不支持中间0省略的情况.
ipv4字符串与整型互转
IPV4字符串转整型,因为整型占4个字节,可用一个无符号整型进行存储。
typedef unsigned char U8;
typedef unsigned int U32;
typedef U8 IPv6Addr[16];
typedef U32 IPv4Addr;
IPv4Addr StrToIPAddr(const std::string &ipStr)
{
IPv4Addr ip;
U8 *addr = reinterpret_cast<U8 *>(&ip);
if(sscanf(ipStr.c_str(),"%hhu.%hhu.%hhu.%hhu",addr,addr+1,addr+2,addr+3) == 4)
{
return ip;
}else{
return 0u;
}
}
反之整型转IPV4字符串
std::string IPAddrToStr(const IPv4Addr &ip)
{
char ipStr[16] = "";
const U8 * addr = reinterpret_cast<const U8 *>(&ip);
int n = sprintf(ipStr,"%u.%u.%u.%u",addr[0],addr[1],addr[2],addr[3]);
printf("sprintf n=%d\n",n);
return ipStr;
}
IPV6字符串与无符号数组互转
IPV6字符串转无符号数组
void StrToIPAddr(const std::string &ipStr,IPv6Addr &ipAddress)
{
if (ipStr.empty())
return;
struct in6_addr ipAddr;
if( inet_pton(AF_INET6,ipStr.c_str(),ipAddr.s6_addr) == 1)
{
memcpy(ipAddress,ipAddr.s6_addr,16);
}else{
memset(ipAddress,0,16);
}
}
反之无符号数组转IPV6字符串
void IPAddrToStr(const IPv6Addr &ip,std::string &ipStr)
{
char ipc[INET6_ADDRSTRLEN] = "";
struct in6_addr ipAddr;
memcpy(ipAddr.s6_addr,ip,16);
if ( NULL !=inet_ntop(AF_INET6,(void*)&ipAddr,ipc,INET6_ADDRSTRLEN) )
{
ipStr.assign(ipc);
}
}
如有更好的方式,望不吝赐教。