Linux网络编程小知识(字节序IP格式函数子网掩码DNS域名解析)

Posted 行稳方能走远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux网络编程小知识(字节序IP格式函数子网掩码DNS域名解析)相关的知识,希望对你有一定的参考价值。

摘自:网络编程前的一些小知识–Linux笔记
作者:一只青木呀
发布时间: 2021-04-12 23:19:10
网址:https://blog.csdn.net/weixin_45309916/article/details/115560197

摘自:DNS域名解析
作者:一只青木呀
发布时间: 2021-04-18 12:48:39
网址:https://blog.csdn.net/weixin_45309916/article/details/115825036

大端与小端

对一个多字节的数字来说在内存中的存储是有顺序的,一般分为大端与小端:

例如:0x12345678

靠近0x的为大端,尾巴为小端。

本地字节序

在我们的内存中一般都是采用小端的方式存取,也就是小端在前大端在后:

0x78 0x56 0x34 0x12

网络字节序

但是在我们的网络传输中一般都是采用大端的方式传输,也就是大端在前小端在后的顺序:

0x12 0x34 0x56 0x78

IP格式

一般的IP格式分为点分时进制(字符串形式)与二进制的格式(int类型)。

点分时进制转换成二进制

in_addr_t inet_addr(const char *cp) //转换网络主机地址(点分十进制)为网络字节序二进制值

一般在TCP的绑定中,sockaddr_in这个结构体的填充时会使用到

在处理地址为255.255.255.255时也返回-1,虽然它是一个有效地址,但inet_addr()无法处理这个地址

点分十进制(Dotted Decimal Notation)全称为点分(点式)十进制表示法,是IPv4的IP地址标识方法。IPv4中用四个字节表示一个IP地址,每个字节按照十进制表示为0255。点分十进制就是用4个从0255的数字,来表示一个IP地址。如192.168.1.1。

网络字节序的二进制转点分十进制

char *inet_ntoa(struct in_addr in)

功能是将网络地址转换成“.”点隔的字符串格式。方便我们在网络编程的时候打印查看IP地址。

点分十进制转网络字节序的二进制

int inet_aton(const char *cp, struct in_addr *inp)

功能是将一个字符串IP地址转换为一个32位的网络序列IP地址。如果这个函数成功,函数的返回值非零,如果输入地址不正确则会返回零

该函数返回值指向保存点分十进制的字符串地址的指针,该字符串的空间为静态分配 的,所以在第二次调用这个函数时,意味着上一次调用并保存的结果将会被覆盖(重写)

常用的比较好的函数

int inet_pton(int family, const char *strptr, void *addrptr)

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len)

现在一般都是采用inet_pton代替inet_addr
inet_ntop代替inet_ntoa

inet_pton源码:

int inet_pton(int family, const char *strptr, void *addrptr)
{
    if (family == AF_INET) {
	    struct in_addr  in_val;
		if (inet_aton(strptr, &in_val)) {
		    memcpy(addrptr, &in_val, sizeof(in_val));
		    return (1);
		}
	}
	errno = EAFNOSUPPOPT;
	return (-1);
}

inet_ntop源码:

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
{
	const u_char *p = (const u_char*)addrptr;
	if (family == AF_INET) {
		char temp[INET_ADDRSTRLEN];
		snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
		if (strlen(temp) >= len) {
		    errno = ENOSPC;
		    rturn (NULL);
		}
		strcpy(strptr, temp);
		return (strptr);
	}
	errno = EAFNOSUPPOPT;
	return (NULL);
}

子网掩码

IP地址是以网络号和主机号来标示网络上的主机的,我们把网络号相同的主机称之为本地网络,网络号不相同的主机称之为远程网络主机,本地网络中的主机可以直接相互通信;远程网络中的主机要相互通信必须通过本地网关(Gateway)来传递转发数据

子网掩码的组成

子网掩码是由长度为32位二进制数组成的一个地址,子网掩码32位与IP地址32位相对应,IP地址如果某位是网络地址,则子网掩码为1,否则为0,例如:11111111.11111111.11111111.00000000(255.255.255.0)

子网掩码的表示方式

  • ①、11111111.11111111.11111111.00000000表示255.255.255.0

  • ②、IP/24 同样表示 11111111.11111111.11111111.00000000(斜杠后面的数字代表着1的个数)

子网掩码的运算

子网掩码与IP之间的运算采用“按位与”的方式计算

例如:网上找个例子
在这里插入图片描述
按位与,采用有0则0的原则计算,得到192.168.10.0

网络地址计算小技巧:IP地址和子网掩码做与运算,把IP地址的主机位直接归0,就快速得到网络地址。所以只要一看到IP地址和子网掩码,就能马上确认网络地址。

DNS域名解析

原理

我在在通过域名解析获取IP的过程中一般使用的是DNS域名解析。

DNS协议是一种应用层协议,他是基于UDP来实现的。
在这里插入图片描述

代码实现

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

extern int h_errno;

int main(int argc, char **argv)
{
	char   *ptr, **pptr;
	char    str[INET_ADDRSTRLEN];
	struct hostent *hptr;  //
	while (--argc> 0) 
	{
		ptr = *++argv;  //传入的域名
		if ( (hptr = gethostbyname (ptr) ) == NULL)   //完成域名解析
		{
			printf("gethostbyname error for host: %s: %s",ptr, hstrerror (h_errno) );
			continue;
		}
		printf ("official hostname: %s\\n", hptr->h_name);
		for (pptr=hptr->h_aliases; *pptr!= NULL; pptr++)
			printf ("\\talias: %s\\n", *pptr);
		switch (hptr->h_addrtype) 
		{
			case AF_INET:
				pptr = hptr->h_addr_list;
				for ( ; *pptr != NULL; pptr++)
					printf ("\\taddress: %s\\n",inet_ntop (hptr->h_addrtype, *pptr, str, sizeof (str)));  //hptr->h_addrtype我们获取的IP地址
				break;
			
			default:
				printf("unknown address type");
				break;
		}
	}
	exit(0);
}

测试

在这里插入图片描述

详细的DNS知识可继续参照这篇博文:DNS服务(域名系统、过程、bind、配置文件、查看本设备dns)

以上是关于Linux网络编程小知识(字节序IP格式函数子网掩码DNS域名解析)的主要内容,如果未能解决你的问题,请参考以下文章

2019.9.24 网络ip小知识

转: 如何用linux命令修改linux主机ip网关子网掩码

IP地址和子网划分学习笔记之《知识学习篇:子网划分详解》

Linux配置网络参数之IP地址、子网掩码、网关地址,DNS

怎样根据IP地址和子网掩码计算出主机号

子网掩码网络类型IP(IPV4)地址类型VLSM CIDR相关知识