前言
以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定
引入
接续上一篇理解计算机系统_网络编程(1)-CSDN博客
国际互联网
Internet的硬件与软件组织
本书原话如下(黑体字):
全球IP因特网是最著名和最成功的互联网络实现.以下是一个客户端--服务器应用程序的基本硬件和软件组织
每台因特网主机都运行实现TCP/IP协议,几乎每个现代计算机系统都支持这个协议
----解读:从图中可以看出,TCP/IP协议由操作系统内核支持,并对外提供套接字接口.程序员是面向套接字接口编程的.用户代码将由系统调用转化成机器代码控制硬件(网络适配器)完成数据传送.
程序员怎样看待网络
从程序员的角度,我们可以把因特网看做一个世界范围的主机集合,满足以下特性:
1.主机集合被映射为一组32位的IP地址
2.这组IP地址被映射为一组称为因特网域名的标识符
3.因特网主机上的进程能够通过连接和任何其他因特网主机上的进程通信 ---黑体字是原话
----解读:不管主机是客户端还是服务器,都以IP地址在网络上标识其身份.对于服务器而言,IP地址被映射成因特网域名.客户端与服务器之间通过连接进行通信
====================内容分割线↓============================================
IPv4和IPv6
理论上IPv4已经够用了
问题:互联网上主机拥有自己的IP地址,IP地址是32位,最大数是40多亿,意味着超过这个数字的主机设备将不能联网,但事实真的如此吗?
答案是否定的.之前笔者提到过以多个数据来建立"层级"或者更大数据的例子.例如:8位机理论上可以寻址个数也可以是无限的,原理是通过"指针"来延展.单个8位能表达256个数,而当8位数据放的是指针,用2个8位数据就能表达65536个数,即达到16位数的效果.
IP地址的延展基于相同的思想.一个IP地址本来用作映射一台主机,当用一个IP地址映射一个网关的时候,这个IP地址可以表示一个子网络里的n台主机,如果n台主机仍觉得不够,那么在子网络中的某个IP地址再次用作网关,这时最初的那个IP地址可以表示(n-1)*(n-1)台主机,依此类推.当然这是一种简化的表达,其中可能牵涉到带宽分配,路由算法等细节,笔者不知道具体实现,但有这样的技术.
这种思想也可以放入数据结构中,建立层级的数据类型,笔者以前帖子中有所提及,可翻看
====================内容分割线↑============================================
接下来部分内容逐一分析IP地址,域名映射,主机通信
IP地址
本书原话:一个IP地址就是一个32位无符号整数,网络程序将IP地址存放在以下结构中
struct in_addr{uint32_t s_addr;
}
----解读:一个标量地址被放入一个结构中,有些令人费解,用个全局变量就可以表达的.而本书对此表示承认,说"是套接字接口早期实现的不幸产物",目前体会不到,不作解读.
大端法和小端法
本书原话:在IP地址结构中存放的地址总是以(大端法)网络字节顺序存放的,即使主机字节顺序是小端法.
----解读:大端法和小端法没有多难,但可以加深对数据存储和访问的理解,所以值得一说.
假设有个32位地址0x12345678,里面的数字是0x11223344.用C语言表示如下:
int *p= 0x12345678; //指针指向该地址
*p=0x11223344; //赋值
p+=4; //往下偏移4,指向0x1234567c
有一个问题:每次指针偏移4,指向下一个地址,那中间地址数据在哪里?0x12345679,0x1234567a,0x1234567b?
实际上*p=0x11223344这个32位数包含了这三个字节的值.一个字节是8位,最大表示0xff(十进制255) .*p把这四个字节的值一起表达了,0x12345678这个地址里的数是0x44,地址79里的数是0x33,地址7a里的数是0x22,地址7b里的值是0x11.图示如下:
大小端法在字节顺序上有所不同,图示如下:
注意:笔者查了某度,说法似乎不一致.细想是一样的,把左边定义成小端或者右边定义成小端,不影响结果.
相比较,小端法适合思维习惯(当然也可能是先入为主,先学主机表示再学网络).
对于程序员来说,大端法和小端法不会影响代码,不必去纠结.那么为什么要作区别呢?笔者估计在机器层面,把数据从网络上取下来的时候,位置不同数据不同.程序员只需要记住某种情况下需要调用这个api.
IP地址和点分十进制串之间的转换
具体不知道在什么情况下能用得上,所以不做过多解读.
记住一个例子:十进制串0xffffffff对应的IP地址是255.255.255.255
因特网域名
因特网客户端和服务器互相通信时使用的是IP地址.然而,对于人们而言,大整数是很难记住的,所以因特网也定义了一组更加人性化的域名,以及一种将域名映射到IP地址的机制.---黑体字是原话
---解读:域名的由来
域名集合形成一个层次结构
一旦一个组织得到一个二级域名,那么他可以在这个子域中创建任何新的域名.如cs.cmu.edu
---解读:创建一个网站至少需要二级域名.
DNS数据库
因特网定义了域名集合和IP地址集合之间的映射.直到1988年,这个映射都是通过一个叫做HOSTS.TXT的文本文件来手工维护.从那以后,这个映射通过分布世界范围内的数据库DNS(Domain Name System,域名系统)来维护.
DNS数据库由上百万的主机条目结构组成,其中每条定义了一组域名和一组IP地址之间的映射.从数学意义来讲,可以认为每条主机条目就是一个域名和IP地址的等价类.
---解读:条目类试设计
//不太可能设计
struct Entry{vector<string> domain_name;vector<string> IP_address;
}
域名系统包含有上百万个Entry对象,可对其进行添加,查找和修改等操作.试试看着不太可能,同样应选择"层级"的数据结构---笔者前面帖子有阐述
//有可能设计
struct Com{string next_name;vector<string> IP_address;vector<Com> com;
}
查找算法:将域名按照"."隔开的字符串取出,每个字符串交给next_name做匹配,如果匹配成功,则IP_address是所需要的字符串集合---即上面的点分十进制串,再将其转化成IP地址,可访问对应服务器.
如果按照这个思路,需要确定一级域名的所有形式,即第一层域名必须只有com,edu,gov,org和net.然后分别写出struct Edu,struct Gov,struct Org和struct Net
注意:能不能写到一起设计个类?因为至少两层域名才得到IP地址,比如csdn.net可以但是net不可以.所以类型设计的时候分开比较好.
域名和IP地址的对应
1>一一对应
一个域名对应一个IP地址
2>一对多
一个域名对应多个IP地址.这种场景比如一个大型网站,流量非常大,需要在全球范围内多个国家架设多个服务器来应对,或者应对其他复杂情形.
3>多对一
多个域名对应一个IP地址
---解读:按照前面条目类型的说法:主机条目就是一个域名和IP地址的等价类(黑体字是原话),也不用考虑那么多,几百万的数据量不是很大,搜索和添加的影响都不大,他的类型设计仍然按照一一对应关系.
因特网连接
本书原话: 因特网客户端和服务器通过连接发送和接收字节流来通信.连接是点对点的,全双工的,可靠的.
连接由"地址:端口"表示.客户端套接字地址由内核自动分配,服务器套接字地址中的端口通常是某个知名端口.
如图,客户端和服务器之间的连接由下列套接字对唯一确定了.
(128.2.194.242:51213,208.216.181.15:80)
---解读:因特网连接的规定,套接字对确定连接,也没说怎么实现的,留待后面内容解读.