网络编程基础 --> 网络通信机理、报文与协议、套接字通信预备

此文我们来剖析你从网上获取的各种资源,是如何历经千辛万苦,跑到你的眼前的!

先来了解一下我们日常使用的大部分应用软件的最基本架构~

C/S 架构与B/S架构

C/S架构(client <—> server)

硬件C/S架构

硬件C/S架构对于我们软件工程师来说可能能够汲取的点不太多,举个例子的话,就比如说传统打印机的服务机制便是一种,这里抛砖引玉一下,有兴趣的话各位可以自行顺藤摸瓜学习这方面的知识

软件C/S架构

C/S架构即此类应用软件拥有客户端/服务端两个组成部分,我们使用的一般是客户端,在使用过程中,我们将自己的数据或需要处理的数据传输到客户端进行保存或处理,并返回处理结果,这个过程的作用机制有些类似于我们平时写程序一样 —> 开发者写代码(客户端向服务器发送请求与数据),开发环境执行代码、判断是否有语法错误并返回输出(服务器处理客户端请求、并返回处理结果)

这种架构使得软件可以同时服务于数以万计的用户(贵司软件处理并发的能力很强的前提下),这也就是互联网行业对比传统行业的优势所在:受众群体理论上不受限制

当你使用客户端要向服务端发送请求或数据时,你的机器会将你要发送的数据放到你本机的缓存中,再通过操作系统调用计算机硬件发送到服务器去,该数据会发送到服务器机器的缓存中,服务器同样从缓存中里拿数据处理请求并返回结果(基于TCP协议)

初步了解了网络通信的基本架构,我们来探讨一个数据发送的过程

B/S架构(Browser <—> Server)

B/S架构即游览器/客户端架构,这类的架构的工作机制与C/S架构基本相同,甚至它们用于定位应用程序的端口都是80(后续会展开介绍),不过该类架构中,开发者就不必再写一个客户端软件了,用户直接使用游览器就可以享受你用代码为他们带去的美好的服务~

计算机网络通信模型

在国际标准化组织提出的计算机网络OSI7层参考模型是:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。

但从应用价值上来说,我们一般讲五层参考模型(TCP/IP五层协议):应用层、传输层、网络层、数据链路层、物理层,如果你是一位开发者,等你了解了一个数据从发送方加工开始到接收方不断拆装读取数据的过程,或许你也会更认可五层参考模型一些(个人建议,不可否认七层模型的学术价值!)

网络编程基础 --> 网络通信机理、报文与协议、套接字通信预备_第1张图片

为什么要分层呢?哎,就和社会上的各位社会主义建设者分为不同的职业一样,大家做的事情不一样嘛!但最终都有一个目的 —> 让世界连起来(让社会人民安居乐业)!

各层的协议及主要作用

网络存在的意义即跨地域通信!
网络 = 物理介质(电磁波、光纤、海底光缆等) + 通信协议
(注:通信协议的实现,是基于各种算法的,比如TCP协议是基于Nagle算法)

协议规定了数据的传输格式:
报文格式:头部 + 数据部分

每当我们发送/接收数据,其实就类似于一个寄包裹/拆包裹的过程,而物理介质就是我们的物流、快递员;
在物理介质中传送的是数据报文,其头部相当于是记录了收件者的地址等信息,而当接受者收到了数据报文时,要把头部不断的按照协议的规定拆解开来,最终收到了发送者想要发送的数据!

对于我们需要关注的通信协议,我们来介绍一下在五层模型中把每一层主要功能完成的协议~

应用层:产生数据,直接为应用程序服务。
主要协议:http、https

传输层:将大量数据(如果你传的够多的话)分为段,一段一段传(基于端口),基于TCP协议,通过其超时重传与握手机制,这是为了能让接收方确认接收到了数据,在这一段中,通常会给数据加上TCP协议的报文(一般的通信都会使用TCP,得益于它的可靠性)
主要协议:TCP、UDP

网络层:将每一段再分为包,和我们平时打游戏会破防着叫喊"怎么又丢包了!"是一种包~该层中有著名的IP协议,IP协议划分了广播域(后续详细介绍),并在头部中加上了ip头
主要协议:IP、ARP

数据链路层:将每个包再分为帧,该层对物理层的电信号基于以太网(ethernet)协议进行了分组,数据帧分为两部分 ----> 头 + 数据;头包含:源地址和目标地址,该地址是mac地址
主要协议:ethernet协议

物理层:物理层中流淌的就是一个一个比特了,这一层又可以称为“傻瓜层”,它会通过交换机、路由器等传输任何给它的数据,而不会有任何的逻辑机制对数据进行判断、处理,像一个无情的打工机器~

这里是自顶而下介绍的,对于接收者,就会把数据自底而上的不断拆解头部,最终获取数据

网络通信是如何定位到接收者的?

接下来我们对这个传输过程探究的更细致一些,全世界可能有几亿台机器可以接入互联网,怎么就能实现其中任意两者之间的通信呢?
这里就显出较为底层的网络层、数据链路层的强大作用了~

ARP协议

MAC地址与网卡

MAC地址:长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线编号),每个网卡都会有一个唯一的MAC地址,MAC地址的一个作用就是反过来标识机器的网卡。

但凡接入互联网的主机必须有一块网卡,每块网卡在出厂时都会烧制好一个全世界独一无二的地址(网卡在通信的标识过程中发挥了大作用呀~)

IP地址

通过IP协议划分的IP地址,首先帮助我们划分了一个广播域。

为什么叫广播域呢?因为计算机通信的方式,说到底还是基本靠吼(官方术语:广播通信)

就像是你和你的舍友都在宿舍,宿舍就是你们的广播域,你想让舍友A帮助你去厕所帮你搓澡,你大喊一声:“舍友A!来厕所帮我搓澡!”,虽然你叫的是舍友A,但整个宿舍的人都能听到,这就是广播通信。

但是只有舍友A会应答你的请求,对应到计算机通信中,就是虽然整个广播域的计算机都会收到你的消息包,但它们在看包内数据前的第一件事是查看其MAC地址是否和自己相同,相同则读取,不相同则丢弃,就如同你还有个舍友B,他十分想帮你搓澡,但听到你喊的内容中的第一句话就是“舍友A!”,它只有灰心的不再听接下来的内容,继续去做他的事,或者等待着你叫他。

IP地址有两种获取方式:

1.静态获取,即手动配置
2.动态获取 ----> 通过DHCP获取

至于DHCP是什么,大家请先把它理解为操作系统所自带的一个软件就好了~

子网掩码

IPv4由四段八位二进制数组成,即最小的是0.0.0.0,最大的为255.255.255.255

一个合法的IPv4地址的出现,还需要子网掩码的参与,其格式与IPv4的格式是相同的,有时子网掩码会在IP地址后用‘1’的个数去表示

一个合法的ipv4地址组成部分 = ip地址与子网掩码地址做’与’运算
与运算?一位对着一位算,有一得一啦~

报文格式 : (源mac地址,目标mac地址) (源ip地址,目标ip地址)数据
向一台计算机发起通信,一开始是不会知道mac地址的,事先知道的是对方的ip地址
但是计算机的底层通信时基于ethernet以太网协议的mac地址通信
所以必须能够将ip地址解析成mac地址 -----> ARP协议

ARP协议机制

ARP协议:发起通信的计算机会首先计算自己的ip协议与子网掩码以及目标计算机的ip协议与子网掩码,算出网络地址,来对比是否一样;
如果一样,即在同一局域网内,拿到目标计算机的mac地址,则直接广播通信,
如果不一样,则拿到网关的mac地址,将数据包发给网关,由网关转交给目标计算机。

所以被发出的数据时通过这样的方式找到目标机的:
ip地址 + mac地址 ----> 标识全世界范围内独一无二的一台计算机
或者: ip地址 —> 标识全世界范围内独一无二的一台计算机
ip地址 + mac地址 + port -------------> 标识全世界范围内独一无二的一个基于网络通信的应用程序
(端口范围:0-65535,0-1023为系统占用端口)
mac + ip + port + url —> 定位到唯一一个资源

网关

可能大家都知道,公网的IP地址是0.0.0.0,我们可以来把局域网理解为一个小区,那么公网就是你所在的城市街道,也就是所有主机都以访问到的,而网关这个概念可以类比理解为小区大门,局域网的大门。

那么你给你其他学校的女朋友发了一条“在吗宝贝?”,这句话就会首先走出你所在的局域网的网关,而进入公网,再通过路由算法等找到你女朋友所在的局域网,进入她所在的网关,就能进行计算机“吼”通信啦!

当然,网关也得有它的IP地址,就像你今天计划要去你女朋友学校找她玩,你顺着地图走,地图告诉你你已经走到她学校周围了,但她们的学校如果没有一所响当当地标明身份的校门,你可能就会开始越找越远啦。

因此加入到万物互联的主机们,都需具备四个要素
1.本机的ip地址
2.子网掩码
3.网关的ip地址
4.DNS的ip地址
至于DNS的概念,我们再埋下一个坑,之后再探讨~

找寻目标机总结

大部分的报文都会以此具备:以太网头、IP头、UDP(TCP)头、dhcp数据包。

作用机制是:

  1. 最前面的’‘以太网标头’',设置发出(本机)的MAC地址和接收方(DHCP服务器)的MAC地址,前者就是本机网卡的MAC地址
    后者这时不知道,就填入一个广播地址:FF-FF-FF-FF-FF-FF
  2. 后面的’‘ip标头’',设置发出方的IP地址和接收方的IP地址,这时,对于这两者,本机都不知道,于是,发出方的IP地址就设为0.0.0.0,
    接收方的IP地址设为255.255.255.255
  3. 最后的’‘UDP(TCP)标头’',设置发出方的端口和接收方的端口,这部分是DHCP协议规定好的,发出方是68端口,接收方是67端口

这个数据包构造完成后,就可以发出了,以太网是广播发送,同一个子网络的每台计算机都受到了这个包,因为接受方收到的目标MAC地址是FF-FF-FF-FF-FF-FF;
但看不出是发给谁的,所以收到包的计算机还必须分析这个包的IP地址,才能判断是否是发给自己的。

当看到发出方IP地址是0.0.0.0,接收方是255.255.255.255,于是DHCP服务器知道’‘这个包是发给我的’',而其他计算机则可以丢弃这个包。

接下来,DHCP服务器读出这个包的数据内容,分配好IP地址,发送回去一个’DHCP响应’的数据包,这个响应包的结构也是类似的,以太网标头的MAC地址是双方的网卡地址。

IP标头的IP地址是DHCP服务器的IP地址(发出方)和255.255.255.255(接收方),UDP标头的端口是67(发出方)和68(接收方),分配给请求端的IP地址和本网络的具体参数则包含在Data部分。

新加入的计算机收到这个响应包,于是就知道了自己的IP地址、子网掩码、网关地址、DNS服务器等等参数。

网络编程基础 --> 网络通信机理、报文与协议、套接字通信预备_第2张图片

由此作为参照,当你在做网络编程时编写自己的协议时,一定要遵从以下规定:

1、两大组成部分 = 头部 + 数据部分
头部:存放对数据的描述信息(数据目的地、数据的类型、数据的长度)
数据部分:要发送的数据

2、头部的长度必须固定
因为接收端需要通过头部获取所接收数据的详细信息

TCP三次握手、四次挥手与DNS

TCP三次握手

TCP协议由于其传输的可靠性,且能传输大量信息等特性,被更广泛的应用在了互联网的各种业务中。

一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:启动、数据传输、退出(关闭)。

当TCP接收到另一端的数据时,它会发送一个确认,但这个确认不会立即发送,一般会延迟一会儿。ACK是累积的,一个确认字节号N的ACK表示所有直到N的字节(不包括N)已经成功被接收了。这样的好处是如果一个ACK丢失,很可能后续的ACK就足以确认前面的报文段了。

一个完整的TCP连接是双向和对称的,数据可以在两个方向上平等地流动。给上层应用程序提供一种双工服务。一旦建立了一个连接,这个连接的一个方向上的每个TCP报文段都包含了相反方向上的报文段的一个ACK。

序列号的作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段。因为TCP使用IP来传输报文段,而IP不提供重复消除或者保证次序正确的功能。另一方面,TCP是一个字节流协议,绝不会以杂乱的次序给上层程序发送数据。因此TCP接收端会被迫先保持大序列号的数据不交给应用程序,直到缺失的小序列号的报文段被填满。

客户端和服务端通信前要进行连接,“3次握手”的作用就是双方都能明确自己和对方的收、发能力是正常的

第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。 从客户端的视角来看,我接到了服务端发送过来的响应数据包,说明服务端接收到了我在第一次握手时发送的网络包,并且成功发送了响应数据包,这就说明,服务端的接收、发送能力正常。而另一方面,我收到了服务端的响应数据包,说明我第一次发送的网络包成功到达服务端,这样,我自己的发送和接收能力也是正常的。

第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。 第一、二次握手后,服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时,服务端收到了客户端对第二次握手作的回应。从服务端的角度,我在第二次握手时的响应数据发送出去了,客户端接收到了。所以,我的发送能力是正常的。而客户端的接收能力也是正常的。

具体实现过程是:

  1. 客户端发送一个SYN段,并指明客户端的初始序列号,即ISN©.
  2. 服务端发送自己的SYN段作为应答,同样指明自己的ISN(s)。为了确认客户端的SYN,将ISN©+1作为ACK数值。这样,每发送一个SYN,序列号就会加1. 如果有丢失的情况,则会重传。
  3. 为了确认服务器端的SYN,客户端将ISN(s)+1作为返回的ACK数值。

经历了上面的三次握手过程,客户端和服务端都确认了自己的接收、发送能力是正常的。之后就可以正常通信了。

TCP四次挥手

四次挥手是为了节省资源与内存,在双方的通信需求被满足之后,而释放掉连接的过程。

TCP连接是双向传输的对等的模式,就是说双方都可以同时向对方发送或接收数据。当有一方要关闭连接时,会发送指令告知对方,我要关闭连接了。这时对方会回一个ACK,此时一个方向的连接关闭。但是另一个方向仍然可以继续传输数据,等到发送完了所有的数据后,会发送一个FIN段来关闭此方向上的连接。接收方发送ACK确认关闭连接。注意,接收到FIN报文的一方只能回复一个ACK, 它是无法马上返回对方一个FIN报文段的,因为结束数据传输的“指令”是上层应用层给出的

具体实现过程是:

  1. 客户端发送一个FIN段,并包含一个希望接收者看到的自己当前的序列号K. 同时还包含一个ACK表示确认对方最近一次发过来的数据。

  2. 服务端将K值加1作为ACK序号值,表明收到了上一个包。这时上层的应用程序会被告知另一端发起了关闭操作,通常这将引起应用程序发起自己的关闭操作。

  3. 服务端发起自己的FIN段,ACK=K+1, Seq=L 4. 客户端确认。ACK=L+1
    网络编程基础 --> 网络通信机理、报文与协议、套接字通信预备_第3张图片

DNS

DNS(Domain Name System)即域名解析系统,我们在日常生活中所访问的网站都具有它的IP地址与端口(一般服务端端口默认为80),但如果我们访问百度需要输入“xxx.xxx.xxx.xxx / xx”,哈,记一个两个IP还好,可全球有上亿个网站呀!通过域名解析系统,我们可以把一些网站的IP映射为一个我们自定义的域名来便于理解与记忆。简单来说呀,它类似于一个字典,域名对应IP与端口,查询的过程是基于UDP协议的。

DNS的查找步骤

  1. 用户在 Web 浏览器中键入 “example.com”,查询传输到 Internet 中,并被 DNS 递归解析器接收。
  2. 接着,解析器查询 DNS 根域名服务器(.)。
  3. 然后,根服务器使用存储其域信息的顶级域(TLD)DNS 服务器(例如 .com 或 .net)的地址响应该解析器。在搜索 example.com 时,我们的请求指向 .com TLD。
  4. 然后,解析器向 .com TLD 发出请求。
  5. TLD 服务器随后使用该域的域名服务器 example.com 的 IP 地址进行响应。
  6. 最后,递归解析器将查询发送到域的域名服务器。
  7. example.com 的 IP 地址而后从域名服务器返回解析器。
  8. 然后 DNS 解析器使用最初请求的域的 IP 地址响应 Web 浏览器。
  9. DNS 查找的这 8 个步骤返回 example.com 的 IP 地址后,浏览器便能发出对该网页的请求:
  10. 浏览器向该 IP 地址发出[ HTTP]请求。
  11. 位于该 IP 的服务器返回将在浏览器中呈现的网页(第 10 步)。

看过爱情公寓的朋友,可能会对“曾小贤因电视台倡导发展业余兴趣而寻求陆展博的帮助试图一展自己的IT知识,陆展博在胡一菲的蛊惑下,交给曾小贤一个盒子,称为由全世界四个主教持有的“因特网”,其中一个损坏,整个世界的互联网都会瘫痪”。

虽然是看一乐哈,但其实背景故事也是有事实可循的,我想编剧指的所谓的“因特网”可能就是根DNS服务器,全球只有13台,且一模一样!离我们最近的是在日本,大家也可以想象,全球那么多网站下这13台服务器得每时每刻承受着什么样的并发量,如果其中一台因为并发量过大而瘫痪了,那么这一台的并发量就会分散到其他12台中,每一台可能就承受着比已瘫痪的第13台更大的并发,说不定一时间,世界的互联网还真会瘫痪(基于个人的狂想与愚见)。

套接字通信预备

之前我们说过:mac + ip + port + url —> 定位到唯一一个资源
URL地址是用来访问资源的:是应用层提供的 —>
URL地址分为三部分:
1.域名+端口
2.应用层协议(HTTP等)
3.虚拟地址

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

把包封起来并往外发的过程需要应用到套接字;
套接字是帮助把数据基于网络协议实现通信。

套接字、传输层到物理层的通信协议的实现是由操作系统来完成的。

套接字是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

把包封起来并往外发的过程需要应用到套接字;
套接字是帮助把数据基于网络协议实现通信。

套接字、传输层到物理层的通信协议的实现是由操作系统来完成的。

套接字是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

以上内容若有不正之处,恳请您不吝指正!

你可能感兴趣的:(网络,服务器,网络协议,python)