网络编程
软件开发架构
什么是软件开发架构?
类似于前面写的ATM和选课系统所用到的三层架构
程序员在编写软件的时候应该遵循的架构设计
软件开发架构的分类
-
C/S架构
C:client(客户端)
S:server(服务端)
客户端相当于是需要体验服务的客人
服务端相当于是对外提供服务的店面
手机上下载的各种app其实是各大厂家的客户端
服务端是为客户端服务的,服务的内容诸如向客户提供资源,保存客户端数据等。
打开app使用功能的时候其实就是基于网络取到厂家的店(服务端)里面让服务员给你提供服务
-
B/S架构
B:browser(游览器)
S:sever(服务器)
B/S架构本质也是C/S架构
让游览器充当各个厂家的客户端 用户无需对应下载相应客户端
服务器其实就是上面放着服务端程序的计算机
两种架构的优缺点
C/S架构:
优势:针对客户端可以高度定制
劣势:需要用户去下载才能使用
B/S架构:
优势:无需下载 急速体检
劣势:无法做到高度定制 体验效果较差
目前的趋势其实更加偏向于B/S架构
微信小程序
只需要下载一个微信就可以通过微信去访问很多服务端
支付宝诸多应用
只需要下载一个支付宝就可以通过支付宝体验很多服务
统一提供接口服务>>>:获取大量用户及数据 中途还可以提供广告服务

网络编程简介
网络编程
网络编程的研究前提就是基于互联网 网络编程就是基于互联网编写代码
网络编程的目的/结果
学习完网络编程之后就可以开发C/S架构的软件(掌握原理 使用框架)
网络编程发展史
该技术源于美国军方>>>:很多先进的技术都是由军事发明后续转为民用
实际应用:
军方想要实现不同计算机之间数据交互
没有网络编程技术的时候只能拿U盘拷贝并携带
为了跨区域交互数据所以发明了网络编程
早期远程通信
1.座机电话
彼此打电话需要电话线
2.打屁股电脑
数据交互需要插网线
3.智能手机
数据交互需要无线网卡
远程通信的前提是必须具备一个物理链接介质
eg:电话线 网线 无线网卡
互联网协议
不同计算机之间要想实现无障碍交互
除了需要有物理链接介质之外还需要一套公有的标准
思考为什么不同厂家的手机零部件几乎是一样的
这个标准是>>>:互联网协议(OSI七层协议)

OSI七层协议简介
所有的计算机在生产过程中必须有相同的部分和相同的功能
应、表、会、传、网、数、物
1.应用层
2.表示层
3.会话层
4.传输层
5.网络层
6.数据链路层
7.物理连接曾
协议总结五层
1.应用层(三层)
2.传输层
3.网络层
4.数据链路层
5.物理链接层
OSI七层协议
OSI七层的本质其实就是规定了数据要想基于网络发送出去必须在计算机上经历一些固定的流程
物理链接层
物理链接介质,传递电信号
数据链接层
基于物理链接层接收到一串二进制数 如何切分才能正常解析?
1.规定了二进制数据的分组方式
2.规定了'以太网协议'
但凡能够接入互联网的计算机都必须有一块网卡
每块网卡在出厂的时候都会被烧制一个全世界独一无二的编号
该编号是由12位16进制数组成
前六位是产商编号
后六位是流水线号
这个独一无二的编号也有一个称呼>>>:'mac地址'(类似身份证号码)
ps:基于mac地址就可以实现计算机之间的数据通信了!!!
网络层
IP协议
规定了每台接入互联网的计算机都必须有一个IP地址(取决于网线)
IP地址目前有两个版本
IPV4:点分十进制
最小::0.0.0.0
最大:255.255.255.255
随着社会的进步 计算机的使用越来越普遍 IPV4地址不够用
IPV6:十六进制
IPV6可以表示出地球上每一粒沙子
ps:IP地址可以唯一标识地球上独一无二的一台接入互联网的计算机
IP地址分为公网IP和私网IP
公网IP是可以直接被游览器访问到的但是私网IP(动态的)是不可以的
我们所有人的电脑默认使用的都是私网IP
公网IP需要花钱购买并且需要实名认证并备案
很多非法网站都是在往外注册备案
传输层
RORT协议(端口协议)
一台计算机上面可以运行很多数据交互软件比如微信、qq、钉钉它们都是从内存中获取数据 为什么不会错乱,就是因为端口协议的存在
端口协议用来标识一台计算机上面正在运行的应用程序(端口号类似于房间号,想找这个程序的数据就根据这个数据的房间号去查找)
端口号的范围是:0~65535
0~1024:系统经常使用的端口号
1024~8000:常用软件端口号
我们以后在些项目的时候推荐使用8000之后的端口
1.同一时间同一台计算机上面端口号不能冲突
2.端口号是动态分配的
eg:打开微信随机分配一个没有被使用的端口号8888
关闭微信重新打开那么会随机分配端口号,可能还是8888也可能是其他
IP地址: 用于标识全世界独一无二的一台接入互联网的计算机
PORT号:用于标识一台计算机上面的某一个应用程序
IP+PORT:能够标识全世界独一无二的一台计算机上面的某一个应用程序
我们日常生活使用游览器访问的各个网址其实就是IP+PORT
www.baidu.com 好记
14.215.177.29:80 难记
ip:port
很多常见的服务器都不需要指定端口 只要访问了ip地址内部去会自动映射
域名解析
将好记的地址解析成真正的地址
www.baidu.com 解析 202.108.22.5:80
应用层
这里完全可以取决于程序员自己
HTTP协议 HTTPS协议 FTP协议 自定义协议
TCP与UDP协议
这两个协议都属于传输层
TCP协议
流式协议、可靠协议
基于TCP协议进行数据交互之前需要做一系列复杂的操作>>>:三次握手四次挥手
三次握手建立链接
四次挥手断开链接
洪水攻击:服务端接受到了大量的syn请求处于rcvd状态
控制很多太计算机同一时刻去访问服务端 造成服务端瞬间过载瘫痪
UDP协议
丢包协议、不可靠协议
不需要建立双下通道 数据的传输速度快 但是可能会丢失
qq使用的就是UDP协议 所以有时候会产生数据丢失现象
但是我们可以在UDP协议的基础之上做很多额外的扩展来保证数据的安全
TCP协议之所以比UDP协议可靠是因为TCP协议发送消息有反馈机制,基于TCP发送的消息会在本地先保存该消息,如果地方确认收到才会删除,否则在一定的时间内会频繁的多次发送直到确认或者超时为止
UDP协议发送数据之后会立刻删除内存数据 不会保存

网络只是补充
-
什么是互联网
将计算机彼此链接到一起的介质
-
互联网建立的目的
基于互联网做数据交互
-
上网的本质
基于网线去访问其他计算机上面的资源
其实我们的计算机也可以称之为是服务器/服务端(专门对外提供服务)
专业设施名词
-
交换机
让接入交互机的多台计算机之间彼此互联
-
局域网
由交换机组成的网络称之为局域网(一个区域)
-
广播与单播
广播:在交换机中群发
单播:定向回复消息(记录mac地址)
-
路由器
将局域网彼此链接起来并支持数据交互
互联网其实可以看成是由多个局域网链接在一起
在局域网中可以直接基于mac地址实现数据交互,mac地址只能用于局域网交互数据,不能跨局域网传输。但是在局域网内可能会产生广播风暴:交换机中同一时间出现太多广播操作
域名解析
域名解析是把域名指向网站空间IP,让人们通过注册的域名可以访问到网站的一种服务。IP地址是网站上标识站点的数字地址,域名解析作用就是为了方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转换过程。该工作由DNS服务器完成。将好记的域名解析成IP,服务由DNS服务器完成,是把域名解析到一个IP地址,然后在此IP地址的主机上将一个子目录与域名绑定。
DNS服务器(域名服务器)
把域名翻译成IP地址的软件称为域名系统,即DNS。是进行域名和与之对应的IP地址转换的服务器。DNS中保存了一张域名和与之相应的IP地址的表,来解析消息的域名。了解:域名是Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。域名是由一串用点分隔的名字组成的,通常包含组织名,而且始终包括两到三个字母的后缀,以指明组织的类型或该域所在的国家或地区。
TCP三次握手和四次挥手每个阶段的含义
三次握手:
第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
符号:
seq(sequence number),序列号,用来标记数据段的顺序,TCP把连接中发送的数据字节都编上一个序号,第一个字节的编号由本地随机产生
ack(acknowlege number),确认号,指的是期望接收到下一个字节的编号,因此当前报文段最后一个字节的编号+1即为确认号
ACK(acknowledgement),确认,当ACK=1确认号字段才有效,ACK=0确认号无效
SYN(synchronous),同步,连接建立时用于同步序号
状态:
CLOSED: 这个没什么好说的了,表示初始状态。
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_RECV: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
SYN_SENT: 这个状态与SYN_RECV遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
ESTABLISHED:这个容易理解了,表示连接已经建立了。
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
题目
为什么是三次握手,而不是两次或者四次
1、根据图中三次握手的信息来看,第一次客户端发送连接请求,第二次服务器接收请求并响应,如果两次的话,可能会出现以下问题,由于网络原因,客户端可能接收不到服务器的响应,那么客户端会认为服务器没有同意它的连接,而服务器确已经开始和客户端的连接了,浪费服务器的资源
2、因为三次握手已经可以满足连接的需求了,三次握手是理论上的最小值,为了提高效率,因此没必要采用四次连接
这里是引用为什么等待2MSL
1、在主动方发送出最后的ACK回复,但该ACK可能丢失。被动方如果没有收到ACK,将不断重复发送FIN片段。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,主动方都没有再次收到FIN,那么主动方推断ACK已经被成功接收,确保被动方已经断开连接,则结束此次TCP连接。
2、等待2MSL就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这 是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一 个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未 必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文 和FIN报文多数情况下都是分开发送的。
为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
因为虽然双方都同意关闭连接了,而且握手的4个报文也都发送完毕,按理可以直接回到CLOSED 状态(就好比从SYN_SENT 状态到ESTABLISH 状态那样),但是我们必须假想网络是不可靠的,你无法保证你(客户端)最后发送的ACK报文一定会被对方收到,就是说对方处于LAST_ACK 状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT 状态的作用就是用来重发可能丢失的ACK报文。
关闭TCP连接一定需要4次挥手吗?
不一定,4次挥手关闭TCP连接是最安全的做法。但在有些时候,我们不喜欢TIME_WAIT 状态(如当MSL数值设置过大导致服务器端有太多TIME_WAIT状态的TCP连接,减少这些条目数可以更快地关闭连接,为新连接释放更多资源),这时我们可以通过设置SOCKET变量的SO_LINGER标志来避免SOCKET在close()之后进入TIME_WAIT状态,这时将通过发送RST强制终止TCP连接(取代正常的TCP四次握手的终止方式)。但这并不是一个很好的主意,TIME_WAIT 对于我们来说往往是有利的。
