Linux 网络初识
一.Linux网络学习脉络
从本章开始我们进行Linux网络的学习。对于网络部分,大致的学习框架如下:
1.网络基础——宏观概念,相关逻辑线
2.写代码:网络socket,udp,tcp
3.写代码:应用层,字节流,序列化,反序列化,自定义协议
4.网络原理:自顶向下
5.高性能服务器:select/poll/epoll。Reactor设计模式:线程池与进程版
二.网络基础
1.互联网产生的历史
互联网的世界,一定是现有计算机——操作系统——网络。一开始,计算机之间都是相对独立的,基本只有科学家和研究人员接触计算机。
在没有网络时的计算机协作如下:数据需要协作处理,主要通过软盘等设备拷贝数据,然后交给下一台计算机。

网络互联:将计算机互联,计算机信息共享不再需要人为拷贝。

结论:
计算机是人类的工具,人的协作也注定了计算机之间的协作,网络的诞生也是必然的。
那么网络具体是如何产生的?
都是先从局部产生的(星星之火可以燎原!)。
一个机构内部的问题解决了,而不同机构之间要交流,就涉及到了机构间的网络——产生了专线,因此网络的拓扑结构也越来越复杂,这是一个由局部到整体的发展。
网络的历史:初代网络——ARPANET,初始为军用,之后美国将其公开,并且开始组建自己的互联网
局域网LAN:局部到整体,计算机的数量更多,通过交换机和路由器连接

广域网WAN:新的技术诞生,也会伴随诞生新的设备,局域网与局域网的通信通过广域网实现。

运营商采购通讯公司的设备,建设大量的基础设施,需要大量的人,更多的岗位诞生,就诞生了大量的互联网公司,推动生产力的发展。
2.协议初识
只要存在长距离通信,就会有协议,协议可以减少通信的成本,快速形成共识。
协议本质是一种约定!计算机之间,怎么做约定呢?
计算机之间的传输媒介是光信号和电信号,通过频率和强弱来表示01信息,想要传递不同的信息就需要约定好双方的数据格式。
问题:只约定好协议,能进行正常通信吗?还不够,需要多方协作来推动这一工作。
• 计算机生产厂商有很多;
• 计算机操作系统, 也有很多;
• 计算机网络硬件设备, 也有很多;
• 如何让这些不同厂商之间生产的计算机能够相互顺畅的通信? 就需要约定一个共同的标准, 大家都来遵守, 这就是 网络协议;
能指定协议的组织和公司:OSI,只生产标准,不写代码实现。不同开发者和公司拿着这套标准进行自己的软件硬件开发。
可以指定协议标准的组织和公司主要有:
IEEE(电气电子工程师学会)
ISO(国际标准化组织)
ITU(国际电信联盟)
ETSI(欧洲电信标准学会)
等等,具体的组织或公司的职能可以自行搜索。
3.协议分层
协议本质是软件,在设计上为了更好的模块化解耦合,也被设计为层次结构。
分层的优势:如果两个人在电话中用汉语交流,在用户层我们会认为是直接进行通信的。然而对于工程师来说,A说的话是经过压缩加密等操作传输给电话,然后对方的电话再解压解密传到B的耳朵中。

结论1:作为普通用户的视角和工程师两种视角看待通信
结论2:我们认为,同层之间可以“直接”通信。
那么我们底层的设备换位了无线电,协议也进行了对应的修改;但是对于用户,我们是感觉不到这种区别的。
同样地,如果通信时用户通信时用的是英语,同样会采用英语协议,而用户也感受不到这种区别。
这就做到了通过分层是实现了解耦!可以更好的排查错误和维护,具有更强大的稳定性。
网络协议栈就是分层的。
4.OSI七层模型与TCP/IP五层模型
1.OSI模型
• OSI(Open System Interconnection, 开放系统互连) 七层网络模型称为开放式系统互联参考模型, 是一个逻辑上的定义和规范;
• 把网络从逻辑上分为了 7 层. 每一层都有相关、 相对应的物理设备, 比如路由器, 交换机;
• OSI 七层模型是一种框架性的设计方法, 其最主要的功能使就是帮助不同类型的主机实现数据传输;
• 它的最大优点是将服务、 接口和协议这三个概念明确地区分开来, 概念清楚,理论也比较完整. 通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯;
大部分教科书都会说OSI复杂不实用,但这并不代表OSI不优秀;其实OSI是一种设计十分优秀且理论完整的模型,它无法完整实现的原因在于,工程师在具体实用这套协议实现网络代码时,某些层的代码是无法实现的。尽管如此,OSI还是有其独特的历史意义。


2.TCP/IP模型
TCP/IP 是一组协议的代名词, 它还包括许多协议, 组成了 TCP/IP 协议簇.
TCP/IP 通讯协议采用了 5 层的层级结构, 每一层都呼叫它的下一层所提供的网络来完成自己的需求.
这里我们仅对每层的功能做大致介绍,不理解也没关系。
• 物理层: 负责光/电信号的传递方式. 比如现在以太网通用的网线(双绞 线)、 早
期以太网采用的的同轴电缆(现在主要用于有线电视)、 光纤, 现在的 wifi 无线网使用
电磁波等都属于物理层的概念。 物理层的能力决定了最大传输速率、 传输距离、 抗
干扰性等. 集线器(Hub)工作在物理层. • 数据链路层: 负责设备之间的数据帧的传送和识别. 例如网卡设备的驱动、 帧同
步(就是说从网线上检测到什么信号算作新帧的开始)、 冲突检测(如果检测到冲突就
自动重发)、 数据差错校验等工作. 有以太网、 令牌环网, 无线 LAN 等标准. 交换机
(Switch)工作在数据链路层. • 网络层: 负责地址管理和路由选择. 例如在 IP 协议中, 通过 IP 地址来标识一台
主机, 并通过路由表的方式规划出两台主机之间的数据传输的线路(路由). 路由器
(Router)工作在网路层. • 传输层: 负责两台主机之间的数据传输. 如传输控制协议 (TCP), 能够确保数据可靠的从源主机发送到目标主机. • 应用层: 负责应用程序间沟通, 如简单电子邮件传输(SMTP) 、 文件传输协议(FTP) 、 网络远程访问协议(Telnet) 等. 我们的网络编程主要就是针对应用层.
由于在Linux网络中,物理层主要是网络的一些电气特性,我们重点研究其他四层的特性。

5.再识协议
协议是计算机遵守的。在操作系统角度,应该如何理解协议?
先来说说为什么要有TCP/IP协议。
本地通信:所有设备都是通过线连接的,计算机内部(冯诺依曼体系结构),本身就是一个网络结构:系统总线,IO总线…是一种通信!
对计算机内的设备进行集群化:这样的公司,就是一个超大型计算机。
网络通信:多台主机通过网络通信,把A主机想想为CPU,把B主机想象为内存,本质也是设备到设备的通信。
也就是说,本地通信本质上和网络通信一样,都是设备到设备的通信。
区别:单纯的距离变长了,但这也引发了新的问题。
问题:A和B主机,距离变长会出现啥问题?
数据丢了怎么办?怎么定位目标主机?怎么解决当下立即要去哪里的问题?如何处理数据?
这些问题在本地基本上不存在,因为在同一台主机中各设备由线直连!
但是,有问题就一定会出现解决问题的方案。
什么方案?TCP/IP协议!这就是网络长距离通信的解决方案!

发送数据不是目的,而是手段,最终的目的都是为了处理数据。

TCP协议能够分层,原因在于问题本身能分层。
现在来回答操作系统怎么看到TCP/IP协议。

数据链路层主要用于局域网通信,在网卡的网卡驱动中实现;
传输层、网络层在操作系统内核实现;
应用层在用户部分实现。
既然传输层,网络层在操作系统内核实现,就需要实现接口被调用。整个网络协议栈,都是在体系结构内部的。传输层和网络层在核心位置。
网络就是操作系统的一部分!
OSI和TCP/IP订好了标准:七层协议或者五层协议——这也解释了为什么它只生产协议而不实现,具体的工作交给操作系统工程师对驱动代码操作系统代码等等的编写。不管是什么种类的操作系统,尽管体系结构在实现上有差异,但是它们的网络部分一定是完全一样的。
6.到底什么是协议?
协议,就是约定好的结构体。主机A在传输层有一个结构体,主机B当然也有,并且双方的网络代码是相同的,主机A向B发送这个结构体,主机B可以解析。

问题: 主机 B 能识别 data, 并且准确提取 a=10, b=20, c=30 吗?
回答: 答案是肯定的! 因为双方都有同样的结构体类型 struct protocol。 也就是说,用同样的代码实现协议, 用同样的自定义数据类型, 天然就具有”共识“, 能够识别对方发来的数据, 这不就是约定吗?关于协议的朴素理解: 所谓协议, 就是通信双方都认识的结构化的数据类型因为协议栈是分层的, 所以, 每层都有双方都有协议, 同层之间, 互相可以认识对方的协议
结构体是协议约定的计算机表达。
最直观的理解:快递单,这就是收发双方的协议。
局域网为什么有那么多种?局部到整体的发展。大浪淘沙,只剩下了以太网,令牌环网,无线网。
局部过渡到整体,而整个网络的解决方案,只能有一套:TCP/IP。
现实中的网络,就是多种局域网通信标准+一种广域网通信标准。
问题:为什么要保留多个局域网通信标准?
因为它属于广域网通信的一种底层技术!
三.网络传输的基本流程
1.局域网通信:以太网为例
1.查看网络配置
Linux主机:
ifconfig
wujiahao@VM-12-14-ubuntu:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 10.0.12.14 netmask 255.255.252.0 broadcast 10.0.15.255inet6 fe80::5054:ff:fe8e:5876 prefixlen 64 scopeid 0x20<link>ether 52:54:00:8e:58:76 txqueuelen 1000 (Ethernet)RX packets 23246166 bytes 6141403536 (6.1 GB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 19113357 bytes 3234218968 (3.2 GB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen 1000 (Local Loopback)RX packets 1877656 bytes 312635948 (312.6 MB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 1877656 bytes 312635948 (312.6 MB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Windows主机:
ipconfig
PS C:\Users\lenovo> ipconfigWindows IP 配置PPP 适配器 宽带连接:连接特定的 DNS 后缀 . . . . . . . :IPv6 地址 . . . . . . . . . . . . : 240e:324:206:1e45:ea80:88c9:57bc:30a本地链接 IPv6 地址. . . . . . . . : fe80::ea80:88c9:57bc:30a%48IPv4 地址 . . . . . . . . . . . . : 123.175.154.253子网掩码 . . . . . . . . . . . . : 255.255.255.255默认网关. . . . . . . . . . . . . : fe80::4e09:b4ff:fe19:ff02%480.0.0.0首先回答:两台主机在同一局域网,能否直接通信?
我们举一个例子说明:
原理类似于上课。老师在教室里指名道姓说张三作业在哪里,实际上教室中的所有人都能听见,只不过只有张三会处理这个问题,然后回答老师。这就是局域网通信的原理——泛洪。
每台主机在局域网上由唯一的标识保证主机的唯一性:MAC地址
2.MAC地址是什么?
• MAC地址⽤来识别数据链路层中相连的节点;
• ⻓度为 48 ⽐特位, 即 6 个字节. ⼀般⽤ 16 进制数字加上冒号的形式来表⽰(例如:08:00:27:03:fb:19) • 在⽹卡出⼚时就确定了, 不能修改. mac地址通常是唯⼀的(虚拟机中的mac地址不是真实的mac地址, 可能会冲突; 也有些⽹卡⽀持⽤⼾配置mac地址).
3.局域网通信流程
例如:主机A向主机E在同一局域网内通信,带上收发地址和消息内容,可以看作是一个结构体。在同一局域网内的所有主机,都会收到这个消息,每个主机会校验报文的前两个字段:收发MAC地址,如果自己是接收方,就处理并恢复;如果不是就直接丢弃。

其实不难想到,如果以上面这个网络拓扑结构组织网络,当有多台主机同时发送消息,可能会在物理层造成信息的干扰——高中的早读一样。所以在以太网中,任何时刻只允许一台机器向网络中发送数据。上面产生的干扰我们称之为数据碰撞,没有交换机的情况下,一个以太网就是一个碰撞域。因此,所有发送数据的主机都要进行碰撞监测和碰撞避免算法
以太网本质就是共享资源——临界资源!所有的主机就是一个个执行流,碰撞避免算法使得各主机拥有互斥属性。
2.同一网段内两个主机的通信
1.我们在看待两台主机通信时,要有意识地把他们看作两个网络协议栈在通信,通信的过程必须自顶向下贯穿协议栈,然后由网卡接收数据,同层之间直接通信。

数据发送的原动力,大部分是人的需求驱动的。
网络协议栈每一层都有协议。既然同层都有协议,那么发送的消息都应该带有这个协议,这样接收方就可以根据协议解析消息,添加到消息头部的叫做协议报头。就好像发快递时,商家除了给我们发我们想要的商品,还会打包一个包裹,上面有各种地址联系人信息——这就是协议报头。

一个报文就分为协议报头+有效载荷。消息只有通过网卡才能发送,所以一个报文会一次一次通过协议栈,加上一个一个的协议报头,最终通过物理层的比特流发送

2.我们可以简单看一下内核中IP数据报的报头(上面已经说过网络层和传输层在操作系统内核中定义)
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)__u8 ihl:4,version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)__u8 version:4,ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif__u8 tos;__be16 tot_len;__be16 id;__be16 frag_off;__u8 ttl;__u8 protocol;__u16 check;__be32 saddr;__be32 daddr;/*The options start here. */
};协议就是结构体。当我们把结构体以二进制形式写到文件中,就是向网络中写;另一个执行流从文件中读取这个协议,就是从网络中读。
为什么要自顶向下封装呢?
因为想发送数据的是用户,用户在最上层;而最终发送数据的是网卡,网卡是硬件处于底层,就必须贯穿操作系统,贯穿协议栈。
对于接收方,一定是网卡先接收到报文。同层拿到报文,就会将报头和有效载荷分离——解包过程。
这样也就解释了为什么在同层看来是直接收到的数据,因为我收到的,正是你发送的形式。
几个需要注意的细节:
细节1:不考虑应用层协议,任何协议都包含两个字段:报头必须做到和有效载荷分离的能力
报头中必须包含的内容:如何将自己的有效载荷交给上一层的哪个具体协议
细节2:底层收到报文,但是报文不是发送给当前主机的,就会直接丢弃,不会继续向上解析,上层就会感觉到没接收到报文。
细节3:封装的过程就是入栈过程,而解包的过程就是出栈过程
局域网内的通信,只是链路层发送给链路层的过程。
网卡的驱动程序默认只会把发送给当前主机的报文向上交付,它还有一种混杂模式:当网卡收到消息,不管自己是否为目标接收方,都把消息向上交付——这就是常见抓包工具的原理。
任何一层只关心报头部分,并不关心具体的有效载荷是什么。
具体每一层对数据报的称谓:
• 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在⽹络层叫做数据报
(datagram),在链路层叫做帧(frame). • 应⽤层数据通过协议栈发到⽹络上时,每层协议都要加上⼀个数据⾸部(header),称为封装
(Encapsulation). • ⾸部信息中包含了⼀些类似于⾸部有多⻓, 载荷(payload)有多⻓, 上层协议是什么等信息. • 数据封装成帧后发到传输介质上,到达⽬的主机后每层协议再剥掉相应的⾸部, 根据⾸部中的 "上层协议字段" 将数据交给对应的上层协议处理.
对协议的宏观认识:
1. 要学习的协议,是如何做到解包的?只有明确了解包,封包也就能理解
2. 要学习的协议,是如何做到将⾃⼰的有效载荷,交付给上层协议的?
总结:

数据包封装和分用


3.跨网络传输流程
跨网络,必定涉及到了更长距离的传输,我们先来说说IP地址。
1.认识IP地址
IP协议有两个版本:IPv4和IPv6.接下来的文章如果没有特别提及,都是默认的IPv4地址。
• IP 地址是在 IP 协议中, ⽤来标识⽹络中不同主机的地址;
• 对于 IPv4 来说, IP 地址是⼀个 4 字节, 32 位的整数;
• 我们通常也使⽤ "点分⼗进制" 的字符串表⽰ IP 地址, 例如 192.168.0.1 ; ⽤点分割的每⼀个
数字表⽰⼀个字节, 范围是 0 - 255 ;
IP地址用来标识全球范围内主机的唯一性:公网IP。通过上面查看Linux主机的网络信息,我们可以看到其中的inet字段代表的就是当前主机的IP地址,ether就是MAC地址。在同一主机上,这两种地址都会被配置。
inet 10.0.12.14 netmask 255.255.252.0 broadcast 10.0.15.255ether 52:54:00:8e:58:76 txqueuelen 1000 (Ethernet)这时你可能有问题:不是MAC地址也能标识主机的唯一性吗?为什么还需要IP地址呢?我们用一个例子讲解。
就好比唐僧去西天取经:比如他到达了车迟国,就说:贫僧从东土大唐来,到西天取经。接着跟国王说:我要去西天取经,下一步怎么走?车迟国国王说:你下一步应该去女儿国。因此唐僧下一站去了女儿国。此时唐僧又说,贫僧....女儿国国王说,你下一步应该去....
唐僧取经:有两套地址,从哪来,到哪去——IP地址,以及上一站从哪来,下一站到哪去——MAC地址。更通俗一点:IP地址就是在数据包路由转发时的最终目标地址,而MAC地址是数据包经过上一个或者下一个路由器的地址(路由器作为一个网络设备,有两个网卡,多个端口,多个IP地址)。
路由器有两层:数据链路层和网络层
接下来讲解具体跨网络的信息传输,示意图如下(假设路由器两端的网络,一个是以太网,一个是令牌环网)

路由器:用来连接不同的子网,因此有两张网卡,每个端口都会配置IP地址

主机A发送数据,要自顶向下发送数据。数据包到达网络层,只要有网络层,就具有路由功能!当前要发送的目标主机知道,IP地址明显不在当前网段中,而且主机A不知道这个目的IP具体在哪。所以此时把报文交给路由器。

此时主机A可以跟路由器直接通信:
因为它们是同一个局域网,主机A转发:源MAC,主机A的MAC,目的MAC,路由器的MAC,而IP一直为目的主机B。到达路由器网卡,向上解包。路由器在转发时,不能直接通过网络层交付,而需要重新向下封装,交给网卡转发到目的主机B。而路由器的右侧网卡和主机B正好是同一个局域网。
我们在两个主机和路由器的网络层观察:它们接收到的信息是完全一样的!路由过程中,IP地址不变。
MAC地址一直在变,具体是在路由器向上交付的过程中改变的,只在当前局域网有效。
底层网络是以太网,无线LAN,令牌环甚至是自定义的局域网通信,这都是数据链路层的差异;在网络层+IP地址,给网络提供了一层虚拟化层,让世界上所有网络都叫IP网络。
可不可以只要IP地址?
这个理念在技术上是可以实现的。但是我们知道,这样会带来网络和硬件的强耦合,不利于新老设备的兼容。
4.总结
注意,本章我们讲解的网络基础种不涉及对任何具体类型的协议讲解,但基本了解了:网络是由局部到整体的发展,并且了解到网络的出现主要解决的是长距离通信,以及一些基础的网络设备和协议分层模型,之后的学习会给予这些基础知识展开,尤其是在操作系统内核中定义的传输层和网络层。
