Python3网络编程篇之网络基本知识

C/S架构

C是Client(客户端软件)
S是Server(服务端软件)

客户端基于网络发送消息给服务端的流程

客户端

应用程序是无法直接操作硬件的
应用程序产生的数据存放于自己的内存中,
然后调用接口发送/拷贝给操作系统,
操作系统再根据应用程序指定的规则/协议,调用网卡发送数据

网络传输数据

 ...............................

服务端

服务端软件调用系统接口,想要将数据从操作系统内存中拷贝到自己的内存里
服务端软件操作系统接受到这一指令后,然后按照客户端指定的协议,
从网卡接受数据,然后拷贝给服务端软件

什么是软件

笼统讲,软件就是除了硬件以外的都是软件

什么是协议

协议:在数据外包了一层,是固定长度的。在定制自己的协议的时候,报头一定是固定长度的字节

网络模型

ISO:国际标准化组织,其定制了一个OSI 开放系统互联模型
层次是人为的划分

OSI七层TCP5层TCP4层单位每层的设备每层的协议
应用层应用层应用层HTTP、SMTP、FTP等(主要是来规定数据的格式)
表示层
会话层
传输层传输层传输层数据段四层路由器、四层交换机TCP、UDP
网络层网络层网络层数据包路由器、三层交换机IP、ICMP
数据链路层数据链路层网卡、交换机、网关Ethernet、ARP(IP->MAC)、RARP(MAC->IP)
物理层物理层物理接口层bit双绞线、集线器、中继器

IP地址

IP地址32位,4段点分十进制表示
IP地址的作用:

  1. 标识所在网络
  2. 标识所在网络中的哪一台主机

IPV4地址分为ABCDE类

  1. A类以0打头
    地址范围:0.0.0.0 ~ 127.255.255.255
    私有地址:10.0.0.0 ~ 10.255.255.255
    保留地址:127.x.x.x

  2. B类以10打头
    地址范围:128.0.0.0 ~ 191.255.255.255
    私有地址:172.16.0.0 ~ 172.31.255.255
    保留地址:169.254.x.x

  3. C类以110打头
    地址范围:192.0.0.0 ~ 223.255.255.255
    私有地址:192.168.0.0 ~ 192.168.255.255

  4. D类以1110打头
    不区分网络地址和主机地址
    地址范围:224.0.0.0 ~ 239.255.255.255

  5. E类以11110打头
    不区分网络地址和主机地址
    地址范围:240.0.0.0 ~ 247.255.255.255

  • IP地址的网络号不能全为0,但可以全为1
  • IP地址的主机号不能全为0,也不能全为1
    • 全为0表示本网络,全为1表示广播地址,向本网络所有主机发送消息
  • 子网号可以全为0以及1

端口

端口:用来标识是哪个应用程序
端口:0 - 65535,其中 0 - 1023为系统占用

MAC地址

网络中每台设备都有一个唯一的网络标识,这个地址叫MAC地址或网卡地址,由网络设备制造商生产时写在硬件内部。

MAC地址是48位的(6个字节),通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如08:00:20:0A:8C:6D就是一个MAC地址。其前3字节表示OUI(Organizationally Unique Identifier),是IEEE的注册管理机构给不同厂家分配的代码,用来区分不同的厂家。后3个字节由厂家自行分配。

  • MAC地址最高字节(MSB)的低第二位(LSb)表示这个MAC地址是全局的还是本地的,即U/L(Universal/Local)位,如果为0,表示是全局地址。所有的OUI这一位都是0。
  • MAC地址最高字节(MSB)的低第一位(LSb),表示这个MAC地址是单播还是多播。0表示单播。

socket

socket(套接字)是应用层与TCP/IP协议簇通信的中间软件抽象层。起源于加尼福尼亚大学伯克利分校版本的Unix,也是人们所说的BSD Unix所以也称socket伯克利套接字或者BSD套接字

最初被设计为同一台主机的多个应用程序之间通讯,称之为进程之间的通讯
以及IPC

socket有两个种族:

  • 基于文件型(AF_UNIX)
  • 基于网络型的(AF_INET)默认IPV4,还有用于IPV6的(AF_INET6)

socket是一个门面模式(一个设计模式),将复杂的TCP/IP协议隐藏在socket接口后面。对于用户来说就是socket就是一个模块、一组接口。你只需调用这些接口、方法,让socket去组织数据即可。

电信号

一组电信号称为数据报/数据帧
数据报分成两个部分:

  1. 报头:固定长度,18个字节
  2. 数据:最大1500个字节,最小46个字节

数据包

网络中传输的数据都叫做数据包,数据包中的数据成为数据报
数据报分为:报头数据两个部分

三次握手和四次挥手

通俗版

三次握手

第一次握手:客户端跟服务端说:“我可以连接你吗?”
第二次握手:服务端响应:可以啊,并且顺便询问客户端,我可以连接你吗?
第三次握手:客户端跟服务端说:“可以啊”

四次挥手

第一次挥手:客户端跟服务端说:“我要跟你断开。”
第二次挥手:服务端响应:可以啊
第三次挥手:服务端数据传输完毕后,跟客户端说:“我也要跟你断开。”
第四次挥手:客户端响应:“好的”

加分版

参考源
https://blog.csdn.net/m0_37907797/article/details/103252306

三次握手

刚开始客户端处于closed状态,服务端处于listen状态。
第一次握手

客户端向服务端发送一个SYN报文,并指明客户端的初始化序列号ISN。
此时客户端处于SYN_Sent状态。

第二次握手

服务器收到客户端的SYN报文之后,会以自己的SYN报文作为应答,
并且也指定自己的初始化序列号ISN,同时会把客户端的ISN + 1作为ACK的值,
表示自己已经收到了客户端的SYN。此时,服务器处于SYN_RCVD状态。

第三次握手

客户端收到服务端的SYN报文,会发送一个ACK报文,
当然,也会把服务器的ISN + 1作为ACK的值,
表示已经收到了服务端的SYN报文。
此时,客户端处于established状态。
服务端收到ACK报文之后,也处于established状态,
此时,双方就建立起了连接关系。

三次握手的作用

  1. 确认双方的接受能力、发送能力是否正常
  2. 指定自已的初始化序列号,为后面的可靠传送做准备

为什么要三次握手

为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:
client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。
本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。
于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。
由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。
但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。
采用“三次握手”的办法可以防止上述现象发生。
例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

为什么需要三次握手才能确认双方的接受与发送能力是否正常,而两次却不可以呢?

第一次握手:客户端发送网络数据包,服务端收到了。此时,服务端得到以下结论:客户端的发送能力以及自身的接收能力是正常的
第二次握手:服务端发送网络数据包,客户端收到了。此时,客户端得到以下结论:服务端的收发能力以及自身的收发能力都是正常的
           但是,服务端并不能确认客户端的接收能力是正常的。
第三次握手:客户端发送网络数据包,服务端收到了。此时,服务端得到以下结论:客户端的收发能力以及自身的收发能力都是正常的

ISN是固定的吗?

在三次握手的过程中,最重要的一个功能就是交换ISN。
以便让对方知道接下来接收数据的时候如何按照序列号组装数据。
如果ISN是固定的,那么攻击者很容易猜出后续的确认号,因此ISN是动态生成的。

什么是半连接队列?

服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,
此时双方还没有完全建立其连接,服务器会将这种状态下的请求连接
放入到一个队列里,我们把这样的队列称之为半连接队列。
当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在
全连接队列中。如果队列满了就有可能会出现丢包现象。

关于SYN - ACK 重传次数问题

服务器发送完SYN - ACK包之后,如果未收到客户确认包,服务器进行首次重传,
等待一段时间后仍未收到客户端确认包,会进行第二次重传。
如果重传的次数超过系统规定的最大重传次数,
系统会将该连接信息从半连接队列中删除。
其中,每次重传的时间间隔不一定相同,一般以指数增长,
例如时间间隔为:1s,2s,4s,8s...

三次握手过程中可以携带数据吗?

在三次握手的过程中,第三次握手是可以携带数据的,前两次不能携带数据,
其中一个简单的原因就是会让服务器更容器受到攻击。
对于第三次,此时客户端已经处于established状态,
也就是说,对于客户端来说,他已经建立起了连接,并且已经知道了服务器
的收发能力是正常的了,所以携带数据是没有什么问题的。

四次挥手

刚开始双方都处于established状态,假如是客户端先发起关闭请求,则:

第一次挥手

客户端发送一个FIN报文,报文中会指定一个序列号。
此时,客户端处于closed_wait_1状态

第二次挥手

服务端收到FIN报文之后,会发送ACK报文,
且把客户端的序列号值 + 1作为ACK报文的值,
表明已经收到客户端的报文了,此时,服务端处于closed_wait_2状态。

第三次挥手

如果服务端也想断开连接了,和客户端的第一次挥手一样,
向客户端发送FIN报文,且指定一个序列号。
此时,服务端处于last_ack状态。

第四次挥手

客户端收到FIN之后,发送ACK报文作为应答,
且将服务端的序列号值 + 1作为ACK报文的序列号值。
此时,客户端处于time_wait状态。
需要过一段时间以确保服务端收到自己的ACK报文之后才会进入closed状态。
服务端收到ACK报文之后,就处于关闭连接了,也就处于closed状态。

这里特别需要主要的就是TIME_WAIT这个状态了,就是要理解,为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。
这其中的原因就是:

要确保服务器是否已经收到了我们的 ACK 报文,
如果没有收到的话,服务器会重新发 FIN 报文给客户端,
客户端再次收到 ACK 报文之后,
就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。

至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。
一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,
则代表对方成功就是 ACK 报文,此时处于 CLOSED 状态。

为什么要等待2MSL

2MSL,MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

原因有二:

  • 保证TCP协议的全双工连接能够可靠关闭

  • 保证这次连接的重复数据段从网络中消失

      第一点:如果主机1直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,
      导致主机2没有收到主机1最后作为应答的ACK报文。那么主机2就会在超时之后继续发送FIN,
      此时由于主机1已经CLOSED了,就找不到与重发的FIN对应的连接。
      所以,主机1不是直接进入CLOSED,而是要保持TIME_WAIT,
      当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
    
      第二点:如果主机1直接CLOSED,然后又再向主机2发起一个新连接,
      我们不能保证这个新连接与刚关闭的连接的端口号是不同的。
      也就是说有可能新连接和老连接的端口号是相同的。
      一般来说不会出现这样的问题,但是还是有特殊情况出现:
      假设新连接和已经关闭的老连接端口号是一样的,
      如果前一次连接的某些数据仍然滞留在网络中,
      这些延迟数据在建立新连接之后才到达主机2,
      由于新连接和老连接的端口号是一样的,
      TCP协议就认为那个延迟的数据是属于新连接的,
      这样就和真正的新连接的数据包发生混淆了。
      所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。
    

为什么要四次挥手?

TCP是全双工模式,这就意味着,
当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;
但是,这个时候主机1还是可以接受来自主机2的数据;
当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,
但是主机2还是可以发送数据到主机1的;
当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,
就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。

滑动窗口

所谓滑动窗口,就是在发送一个包之后,不等待ACK号的返回,直接发送后续的一系列包。有效利用等待ACK号的这段时间。

TCP与UDP的区别

TCPUDP
头部20B8B
可靠性可靠不可靠
连接性面向连接无连接
报文面向字节流面向报文
效率传输效率低传输效率高
双工性全双工一对一、一对多、多对一、多对多
流量控制滑动窗口
拥塞控制慢开始、拥塞避免、快重传、快恢复
系统资源要求多要求少
传输速度
应用场景对效率要求低,对准确性要求高或者要求有连接的场景对效率要求高,对准确性要求低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值