IP地址与int32整型之间的转换

问题

有一个IP地址"127.0.0.1" 需要他的四字节整型值?
反过来有一个整型值,如何转换为一个点分十进制的IP地址?
其实libc是提供这个接口的,不需要自己再造轮子,对比我们自己的实现,用到了联合体,非常值得学习,如下:

1、inet_addr

typedef uint32_t in_addr_t;
struct in_addr
{
    in_addr_t s_addr;
};
/*
 * Ascii internet address interpretation routine.
 * The value returned is in network order.
 */
in_addr_t
__inet_addr(const char *cp) {
	struct in_addr val;

	if (__inet_aton(cp, &val))
		return (val.s_addr);
	return (INADDR_NONE);
}
weak_alias (__inet_addr, inet_addr)

/*
 * Check whether "cp" is a valid ascii representation
 * of an Internet address and convert to a binary address.
 * Returns 1 if the address is valid, 0 if not.
 * This replaces inet_addr, the return value from which
 * cannot distinguish between failure and a local broadcast address.
 */
int
__inet_aton(const char *cp, struct in_addr *addr)
{
	static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
	in_addr_t val;
	char c;
	union iaddr {
	  uint8_t bytes[4];
	  uint32_t word;
	} res;
	uint8_t *pp = res.bytes;
	int digit;

	int saved_errno = errno;
	__set_errno (0);

	res.word = 0;

	c = *cp;
	for (;;) {
		/*
		 * Collect number up to ``.''.
		 * Values are specified as for C:
		 * 0x=hex, 0=octal, isdigit=decimal.
		 */
		if (!isdigit(c))
			goto ret_0;
		{
			char *endp;
			unsigned long ul = strtoul (cp, (char **) &endp, 0);
			if (ul == ULONG_MAX && errno == ERANGE)
				goto ret_0;
			if (ul > 0xfffffffful)
				goto ret_0;
			val = ul;
			digit = cp != endp;
			cp = endp;
		}
		c = *cp;
		if (c == '.') {
			/*
			 * Internet format:
			 *	a.b.c.d
			 *	a.b.c	(with c treated as 16 bits)
			 *	a.b	(with b treated as 24 bits)
			 */
			if (pp > res.bytes + 2 || val > 0xff)
				goto ret_0;
			*pp++ = val;
			c = *++cp;
		} else
			break;
	}
	/*
	 * Check for trailing characters.
	 */
	if (c != '\0' && (!isascii(c) || !isspace(c)))
		goto ret_0;
	/*
	 * Did we get a valid digit?
	 */
	if (!digit)
		goto ret_0;

	/* Check whether the last part is in its limits depending on
	   the number of parts in total.  */
	if (val > max[pp - res.bytes])
	  goto ret_0;

	if (addr != NULL)
		addr->s_addr = res.word | htonl (val);

	__set_errno (saved_errno);
	return (1);

ret_0:
	__set_errno (saved_errno);
	return (0);
}
weak_alias (__inet_aton, inet_aton)
libc_hidden_def (__inet_aton)
libc_hidden_weak (inet_aton)

2、inet_ntoa 看源码还是相对比较简单,就是格式化字符串

/* The interface of this function is completely stupid, it requires a
   static buffer.  We relax this a bit in that we allow one buffer for
   each thread.  */
static __thread char buffer[18];
char *
inet_ntoa (struct in_addr in)
{
  unsigned char *bytes = (unsigned char *) ∈
  __snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
	      bytes[0], bytes[1], bytes[2], bytes[3]);
  return buffer;
}

3、测试

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main()
{
	unsigned long a = inet_addr("127.0.0.1");
	printf("a is %d\r\n", a);
	struct in_addr addr1;
	addr1.s_addr = a;
	char *p = inet_ntoa(addr1);
	printf("p is %s\r\n", p);
	return 0;
}

4、运行结果

在这里插入图片描述
完结,注意inet_addr转换后是一个网络字节序,也就是大端,如果是本地使用还需要注意哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值