网络编程--网络理论基础

协议的概念

什么是协议

在这里插入图片描述
在这里插入图片描述
协议就是传输文件双方都严格遵守的一个传输规则,如上图,第一次传输传文件名,第二次传大小,第三次传内容

典型协议

在这里插入图片描述

分层模型

OSI七层模型与TCP/TP四层模型

TCP/IP协议中各个层与OSI各个层的对应关系:
在这里插入图片描述

TCP/IP模型各个层的典型协议:
在这里插入图片描述
一般常用TCP/IP模型
他的不同层有着不同的协议,这些协议都是典型协议

拓展:
在这里插入图片描述

在这里插入图片描述
对于用户层:我们在写程序时,主要是在用户层做操作
对于内核层:在内核层不需要做修改,我们只是在应用层去调用内核层的一些参数,如IP port TCP协议、UDP协议等等

通信过程

在这里插入图片描述
在这里插入图片描述
首先要知道,数据在没有封装之前,是不能在网络中传递的
在这里插入图片描述
对于一个数据,如上图中的“啥时候还钱五角星”,这就是一个数据,
网络传输时,通过a电脑的网卡,将数据发送到网络,再通过网络到b电脑的网卡
但是赤裸裸的数据是不能直接进行传输的,要对其进行封装

我们先对应用层封装,之后拿着这个封装结果,在传输层再封装一层,之后再在网络层封装一层,层层套娃,最后在链路层封装成最后的样子(每一层的封装都要遵守相应的协议),这样就可以通过主机的网卡传到网络,给到b主机
在这里插入图片描述
b主机拿到这个东西之后,要按照在各个层按照相应的协议进行解释,也就是解封装,最终拿到数据
在这里插入图片描述
我们将应用层划为应用层,应用层之下都划为内核层,
我们只需要负责应用层的封装和解释,内核层的封装与解释都交给系统就好
系统封装好了会自动传给网卡,通过网卡传给网络

协议格式

以太网帧协议(主要作用于mac地址,也就是网卡)

mac地址

在这里插入图片描述
首先介绍一下,mac地址就是网卡的id号,相当于网卡的身份证,每一台电脑的网卡都有一个独一无二的mac地址

格式

在这里插入图片描述
可以看到格式:
目的地址:目的地的mac地址,即目的地的网卡地址
源地址:发送端的网卡地址
类型:每个类型有固定的类型号,数据包就是0800类型
ARP数据包就是0806类型

后面是数据以及CRC

我们可以获取到发送端,也就是本机的mac地址,但我们如何拿到接收端的mac地址呢,就需要用到ARP协议

ARP协议

用来获取目的IP的mac地址
在这里插入图片描述
简化成如下格式:
在这里插入图片描述
对于请求的数据包,第一个是以太网目的地址,我们不知道,我们发送ARP就是为了得到他,不知道就是ff:ff:ff:ff:ff:ff,然后依次是发送端mac地址,数据包类型固定0806,中间一大堆8字节空间不细究,之后是发送端以太网地址(即mac地址),发送端IP地址(本机唯一ID号),然后还是目的端以太网地址,最后是目的端IP地址

举例:
在这里插入图片描述
我们以从主机向网络发送数据为例,(注意,网络就是一个一个路由器互联形成的一个网,每个路由器有自己的网卡,有自己的IP)
所以,这里以主机向路由器发送数据包为例,想要发送最终的以太网帧格式的数据包,就要知道对方的mac地址,我们可以通过ARP协议数据包拿到路由器的mac地址,路由器收到请求,会将ARP请求上的目的IP进行广播,看看是哪个路由器的IP,通过IP找到目标路由器,目标路由器会以ARP协议格式进行应答,我们就可以得到路由器mac地址
就可以封装以太网帧协议数据包,将数据从主机传输给路由器

总结

在这里插入图片描述

IP协议(主要作用于IP)

在这里插入图片描述
在这里插入图片描述
首先是版本号
有源IP 以及 目的IP
之后有TTL,对于TTL,他是指数据包的生存时间,如下图:
在这里插入图片描述
当数据被传入到网络中后,由于网络就是一个一个路由器互联而成的网,所以如果通往目的地的网都断开了,该数据包就会一直在该网里来回传送,反复横跳,而当无法到达目的地的数据包增多,这样一来时间一长,就会造成网络的拥堵
在这里插入图片描述
所以,设置了其TTL生存时间,生存时间的单位是跳,表示一个数据包最多在网络中跳转几次,从一个路由器到另一个路由器表示一次跳转,每跳转一次 TTL就-1,当到达一个路由器,TTL减为0时,该路由器会将其数据包丢掉

UDP与TCP协议(主要作用于端口)

这两个协议主要是作用于端口,端口号是在主机中唯一标识一个进程,而IP是在网络环境中唯一标识一个主机,
所以IP+端口号,可以唯一标识一个网络环境下的进程
在这里插入图片描述

在这里插入图片描述
TCP与UDP的区别在于,TCP要建立连接,之后再传输,而UDP是直接传输

!!! 注意,端口最大是65536,所以使用的端口号最大不要超过65536(不包含65536)

网络应用程序设计模式

C/S模式与B/S模式

简介

在这里插入图片描述
C/S模式是客户端与服务器开发,需要通讯两端各自部署客户机和服务器,
比如,一个独立的应用,可以上架应用商店的应用,就是C/S模式

B/S模式是浏览器与服务器开发,只需要在一端部署服务器,另一端使用浏览器就可以
比如,一些依附于浏览器的应用,只能在浏览器上运行

优缺点

在这里插入图片描述
C/S模式可以自己规定协议(即应用层协议,可以不使用http/https,可以自己规定,但是内核层还是调用的系统的标准协议),因为两端的代码都是自己开发,但是站在用户的角度来看,用户的安全性较差,因为协议都是公司规定,公司可以做手脚,同时跨平台较差,不同操作系统的软件数据可能会不相通(比如王者荣耀IOS与安卓不相通)
一些需要大量数据缓存的应用(比如许多特效图片等等需要在应用运行之前提前缓存),使用C/S较为合适

而B/S模式只能严格遵守http,但是安全性高,且跨平台容易
一些不需要缓存大量数据,较为轻量化,希望随时跨平台使用的应用,使用B/S较为合适
在这里插入图片描述

对于“C/S模式的应用层协议自定义”的理解

在我们的服务器server中,体现应用层协议的部分就是一系列IO操作,即一系列read/write操作的字符串,而协议就指导了我们read的字符串如何解读,也指导了我们如何write字符串

TCP协议

TCP通信时序

在这里插入图片描述
在这里插入图片描述

建立连接阶段

在这里插入图片描述
首先是客户端发起连接请求,用SYN标志位来表示是一条请求,而不是一个实实在在的数据包,相当于是一个带有信息的数据包外壳,同样他具有数据包序号,这是客户端发出的第五百个数据包500,而之后的括号表示该数据包的大小,由于他只是一个外壳,所以是0,即500(0),如果此时有mss<1460>,是默认的,表示客户端发出的任何数据包,数据大小上限是1460字节

之后服务器收到这个请求后,会回复一个回执,用ACK表示“我已收到”,后面会跟上客户端的数据包序号加上数据大小,如上图应该是500+0,但是由于它是一个SYN,数据包外壳也占一字节,所以应该是500+1=501;同时他回复也是一条请求,前面也要加上SYN 自己数据报的序号+(0)

最后客户端会再发一条回复,该回复只需要ACK 即可,而ACK后面的序号就是服务器发送的数据包序号+数据大小或者加一,跟上面规则一样

至此,三次握手完成,但是这个过程是在内核中完成的,我们编写程序是在用户层(应用层),体现在代码中就是accpect与 connect 函数调用成功,并成功返回了返回值

在这里插入图片描述
建立好了三次握手,就对应之前C/S模型中:服务器与客户端之间的socket建立好了连接

数据通信阶段

在这里插入图片描述
在建立完连接之后,进行数据的传输

(从第4开始,是数据通信阶段)
首先是客户端发起一个数据包,无需加任何标志,直接就是数据包序号+(数据大小),但是这里还要发一次ACK8001,与通信阶段最后发送的ACK一致,主要目的是为了保险起见,再发一次

此时数据包的序号是由上一次客户端发出的数据包的序号以及类型决定的
上一次发出的是SYN 则应该是序号+1
上一次发出的数据包,则应该是序号+数据大小

之后服务器收到数据,会回复一个数据包,也就是经过服务器程序处理完之后的数据,发回给客户端,数据包序号顺延上一次服务器发送的数据包序号,规则还是那个序号规则,之后+(数据大小),
再跟上ACK,ACK都是根据对方发来的数据包序号进行顺延,规则还是那个规则

最后客户端表示收到,发送ACK,顺延对方(这里是服务器)发来的数据包序号,序号还是那个规则

批量传输:
在这里插入图片描述
TCP在传输时,会批量传输,

总之,每次发送的数据包,如果是请求,则加上SYN,如果是数据,则不用加,
如果是回复,则只写ACK

之后是数据包序号+(数据大小)ACK不用加数据大小
确定序号:
顺延规则:
自己的数据包顺延自己上一次发送的数据包序号
ACK顺延要回复的对方的数据包序号
序号规则:
上一次发出的是SYN 则应该是序号+1
上一次发出的数据包,则应该是序号+数据大小

四次挥手关闭连接

在这里插入图片描述
首先由客户端发出关闭请求,标志符是FIN 数据序号还是之前的规则,+(0),同时可以强调自己上一次的ACK
之后服务器收到之后,会回复ACK 序号顺延要回复的数据包序号

但此时还没完,这时只完成了一半,(称为半关闭),还要由服务器发出一个断开请求,然后客户端去回复

所以服务器发出FIN 加数据包序号(顺延自己)+(0),之后强调自己上一次的ACK
然后客户端进行ACK回复,序号顺延要回复的数据包序号

补充:
半关闭:
在这里插入图片描述
我们知道套接字就是两个缓冲区,一个是read缓冲区,一个是write缓冲区
半关闭就是将w缓冲区关闭,不能由C向S写数据了,但是可以读数据
(读文件,从一个文件读到数据(获取信息),写文件,将结果输出到某个文件(输出信息)
对于程序而言,以程序为参考,read就是从某个文件读取到数据到程序)
同时,连接还在 没有断开 所以还是可以互相发送请求
只是对于数据传输进行了半关闭

小tips:
可以注意到,在整个程序中,ACK除了第一条没有,其他都会有ACK,他们的作用要不是用来回复,要不就是用来强调一遍

TCP滑动窗口

在这里插入图片描述
在进行TCP传输时,客户端或者服务器他的处理数据的能力有限,他的缓冲区具有固定的大小,如果客户端性能较好,一次性给服务器发送过量的数据,就会导致服务器超负荷,所以,就出现了滑动窗口进行流量控制

在这里插入图片描述
上图中的win后面的数字,就是他们当前能处理的数据量的大小,
比如建立连接阶段,还没有进行数据传输,二者互发的win就是最大的数据处理上限

之后,当客户端向服务器一次次的发送数据,服务器的缓冲区就逐渐被占满,当达到上限后,客户端会停下等待服务器处理

服务器进行一部分处理之后,会腾出来一部分空间,服务器会持续的win出来剩余的可用空间,客户端可根据情况选择是否继续传输数据,到最后数据传输完成,服务器慢慢处理,最后又win整个空间

我们注意到,win会存在于每一条命令里,如果有ACK,会在ACK的后面

通信时序与代码的对应关系

在这里插入图片描述

总结

在这里插入图片描述

TCP状态转换

TCP状态转换图

总览

在这里插入图片描述

主动发起连接(三次握手)

在这里插入图片描述
在这里插入图片描述
首先,我们先来看主动发起连接阶段(也就是三次握手阶段),纠正:图中应该是SYN_SENT,而不是D
刚开始,主动发起端处于关闭状态CLOSE,之后发送SYN标志,随即主动端变为了SYN_SENT状态,然后主动端接收由被动端发来的SYN、ACK,接收之后此时还是SYN_SEND状态,然后只有主动端在接收了之后紧接着向被动端发送ACK,当被动端接收到ACK之后,说明连接建立,主动端的状态才会变为ESTABLISHED状态,此时就是数据通信状态,再之后的互发数据,就是通信过程,那一整个过程都是数据通信状态

我们可以通过终端来查看当前客户端的状态(因为一般都是客户端主动发起请求)
在这里插入图片描述
在已经有两个终端进行通信的情况下,我们可以再开一个终端,进行状态查看,输入命令netstat -apn | grep client(或者端口号8080),使用网络状态查看命令以及管道符过滤,就可以查看到客户端和服务器的状态了,目前两个都处于“数据通信状态”

主动关闭连接(四次挥手)

在这里插入图片描述
在这里插入图片描述
首先主动端和被动端都是“数据通信”状态,
之后,主动端发出FIN,随即,主动端变为FIN_WAIT_1状态,然后被动端发送ACK(以主动端的视角来看是接收ACK)当主动端接收到ACK时,主动端状态变为FIN_WAIT_2(这个状态就表示半关闭状态),之后由被动端发送FIN(即主动端接收FIN),这时主动端还是FIN_WAIT_2状态,之后发送ACK,一旦发送,这时主动端就变为了TIME_WAIT状态,但是还没有进入关闭状态,他距离关闭状态会有个时间缓冲2MSL时长,(linux下一般是40s),经过这个时长,才会到达CLOSE状态,即关闭状态

(补充:如果在FIN_WAIT1的状态下同时收到ACK和FIN,那么会略过FIN_WAIT2,直接进入TIME_WAIT)

我们将服务端ctrl+c结束进程,然后再试图启动server,发现提示Address already in use,意思就是还没进入关闭状态,这时我们通过另一个终端查看8000端口,发现处于TIME_WAIT状态,所以要等待2MSL时长,我们可以一直查看netstast,看他TIME_WAIT状态消失之后,说明可以再次启动服务端了
在这里插入图片描述
在这里插入图片描述

!!注意,如下图:
在这里插入图片描述
我们主动关闭谁,谁就是主动端,上图我们主动关闭客户端,那客户端就是我们之前分析的主动端,他会处于TIME_WAIT状态。而这时再去关闭服务端,他就不会经历TIME_WAIT,所以可以直接去启动服务端,同时客户端也可以启动(因为客户端的端口号是随机分配的、不固定)
但是如果先关闭服务端,那么服务端会进入TIME_WAIT,而这时候再去启动服务端,他会启动失败,因为服务端启动不同于客户端,服务端需要拿到ip地址和端口号,这时TIME_WAIT状态下,端口号都被占用,所以无法给服务端使用,则服务端要等待2MSL时长才可以再启动

被动接收连接(三次握手)

在这里插入图片描述

在这里插入图片描述
首先处于CLOSE状态,之后,一旦进程开始,会立马转换为LISTEN(监听)状态,之后收到SYN,状态不变,还是LISTEN,然后发送ACK和SYN,一旦发送,被动端就变为SYN_RCVD状态,最后接收ACK,就会变为ESTABLISHED(“数据通信”)状态。

补充:如果被动端处于SYN_RCVD状态,一直没有接收到主动端发来的ACK的话,被动端会一直发送请求,直至主动端进行ACK回应
在这里插入图片描述

被动关闭连接(四次挥手)

在这里插入图片描述
在这里插入图片描述
首先处于ESTABLISHED状态,之后收到主动端的FIN,状态不变,还是ESTABLISHED,然后我们发送ACK,一旦发送,被动端就变为了CLOSE_WAIT状态,对端一旦收到ACK,他就完成了半关闭,对应的,我们被动端此时是CLOSE_WAIT状态,
在该状态下查看是否有数据还要发送给对方,如果没有,可以close这个socket,发送FIN,就是在close这个socket。
一旦被动端发送FIN给主动端,我们就变成了LAST_ACK状态,然后接收到对端发来的ACK时,就变成了CLOSE

总结

在这里插入图片描述
2MSL时长是为了以防最后一个ACK没有被对方接收,所以等待看客户端是否会再次发送FIN请求
在这里插入图片描述
今后我们可以对应着这张图,使用终端去查看端口的网络状态,就可以看出他们各自处于什么状态

在这里插入图片描述
在这里插入图片描述

端口复用

使用场景

当我们的服务端由于某些原因不得不停止时,我们就必须要等40秒,这是非常影响用户体验的,所以我们要想办法解决这个问题

简介

在这里插入图片描述
这两行代码是写死的,可以直接记住,第一个参数是listenfd,监听端文件描述符,第二个参数是SOL_SOCKET,第三个参数是SO_REUSEADDR,第四个参数是取第一个变量的地址,形参为(void *),所以可以传入任何一种类型变量的地址,第五个参数是opt的sizeof大小

将这两行代码加到socket()和bind()之间
在这里插入图片描述
这样加完之后,就设置完端口复用了,这样我们如果先停下服务端,再停下客户端,我们就可以直接再启动服务端,无需等待2MSL时长了

半关闭

在这里插入图片描述
辨析:
某一方:客户端或者服务端
某一端:读或者写

半关闭表示通信双方,某一方的通信套接字中,只有一端关闭通信(这里的一端指的是功能:读端或者写端,而不是某一方(如客户端或者服务端)),对应于TCP状态的话是FIN_WAIT2,称该方进入半关闭状态
可以通过close(cfd)进入这种状态,如close(cfd)是关闭cfd的写端,所以cfd进入半关闭(即服务端进入半关闭状态)
还可以通过shutdown(int fd, int how)第一个参数是文件描述符,第二个参数则设置是关闭选择的文件描述符的读or写端or读写端

HTTP协议

请求消息(Request)

内容及举例

在这里插入图片描述
请求消息:表示用户在浏览器做了操作之后,浏览器发送给服务器的请求。

当用户做了某些操作后,浏览器会自动将该操作打包成http协议格式的数据
该协议的数据包含:
1、请求行,即上图中第一行,第一个位置表示请求类型(GET 还是 POST …更多见下面《HTTP请求方法》),之后第二个位置是请求的资源,第三个位置是使用的http版本
2、请求头:如上图第2~8行
第2~8行:是一些服务器要使用的附加信息
(可以看到第7行的Connection的值是keep-alive,表示,http协议的传输层采用的是TCP协议,这里是在进行三次握手建立连接)
3、空行:如上图第9行
第9行:是一个空行,这是必须的,他用于表示请求头部分的内容结束
而请求行+请求头+空行(即刨去数据主体),可以被称为“协议头”
3、请求数据:如果一个请求需要从浏览器携带数据给服务器,那么数据内容会放在第9行之后,也就是“请求数据”部分,如下图:
在这里插入图片描述
如果当前请求是POST请求的话,那么第9行之后,就是请求消息(Request)所携带的相关请求数据

响应消息(Response)

在这里插入图片描述
包括:
1、状态行:即上图第一行,包括http协议版本号,然后是状态码,状态码后面是对状态码的描述,即对状态码的解释。比如上图的200,表示的就是OK的意思,而我们常见的404,表示的就是找不到资源的意思(更多见下面《HTTP常用状态码》)
2、消息报头:上图中第2~8行,说明要传达给浏览器的一些附加信息(第4行和第9行必须有,其他的可以没有)
其中:第4行(必须有),表示这次要发送的数据是什么格式类型的,如(文本类型、img、png类型、mp3类型、mp4类型等等),以及该文件的编码格式(更多见下面《常见网络文件类型》)
第5行,要么不写,要么传-1,要么就算的精确
第8行,表示TCP连接断开,说明,http协议是每进行一次连接,互通一次数据,且立马断开。待下次建立连接,再互通一次数据,再断开
3、空行:在消息报头之后,是一个空行,表示消息报头的结束
状态行+消息报头+空行(即刨去响应正文部分),称为协议头
4、响应正文:即返回给浏览器的数据

HTTP请求方法

在这里插入图片描述

HTTP常用状态码

在这里插入图片描述

常见网络文件类型

在这里插入图片描述
在这里插入图片描述

补充

http协议自学网站:
https://www.runoob.com/

https://www.runoob.com/http/http-tutorial.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值