@ 作者:达内 Python 教学部,吕泽
@ 编辑:博主,Discover304


网络基础知识

什么是网络

计算机网络功能主要包括实现资源共享,实现数据信息的快速传递。

网络通信标准

网络的普及需要标准。不同的国家和公司都建立自己的通信标准不利于网络互连,同时多种标准并行情况下不利于技术的发展融合。

而一个统一 的通信标准不仅可以实现万物互联,也可以降低开发难度。

于是OSI7层模型被提出,并且被行业接受。

索引 层名 说明
7 应用层 各种应用程序
6 表示层 数据格式化、数据加密解密、数据的压缩解压缩
5 会话层 建立、管理、终止应用之间的会话连接
4 传输层 提供端到端的数据服务(可靠或者不可靠)
3 网络层 逻辑寻址;路由选择
2 数据链路层 将分组数据封装成帧
1 物理层 在介质上传输比特;提供物理的规约

OSI7层 模型因其每层功能明确,各司其职,也就是说实际规定了每一层的任务,该完成什么事情,可以很好的的降低开发难度。

之后随着技术的进步和互联网的发展,OSI7层的模型因为过于理想的结构(也就是说结构细节太复杂)、在实际工作中实践难度大等原因,在实际工作中慢慢被TP/IP模型取代。

索引 层名 TCP/IP协议 说明
7 应用层 应用层 Telnet、FTP、SMTP、DNS、HTTP以及其他应用协议
6 表示层
5 会话层
4 传输层 传输层 TCP、UDP
3 网络层 网络层 IP、ARP、RARP、ICMP
2 数据链路层 网络接口 各种通信网络接口(以太网等,物理网络)
1 物理层

上表中提到,TCP/IP是一种网络协议。什么是网络协议呢?在网络数据传输中,都遵循的执行规则,网络协议实际上规定了每一层在完成自己的任务时应该遵循什么规范。

需要应用工程师做的工作有以下几个:编写应用工功能,明确对方地址,选择传输服务。

通信地址

通信地址有两个部分:IP地址和端口号。

IP地址:网络中表示一台计算机的地址编号,下又分IPV4和IPV6两种。IPV6采用的地址格式可以解决IPV4地址紧缺的问题。IPV6号称可以给地球上每一粒沙子一个ip地址。

  • IPv4 特点
    • 分为4个部分,每部分是一个整数,取值分为0-255
    • IPv4 : 192.168.1.5
  • IPv6 特点
    • 分为8个部分,每部分4个16进制数,如果出现连续的数字 0 则可以用 :: 省略中间的0
    • IPv6 :fe80::80a:76cf:ab11:2d73
  • IP地址相关命令
    • ifconfig : 查看Linux系统下计算机的IP地址
    • ping [ip]:查看计算机的连通性
  • 公网IP和内网IP
    • 公网IP指的是连接到互联网上的公共IP地址,大家都可以访问。(将来进公司,公司会申请公网IP作为网络项目的被访问地址)
    • 内网IP指的是一个局域网络范围内由网络设备分配的IP地址。

端口号:网络地址的一部分,在一台计算机上,每个网络程序对应一个端口。

  • 端口号特点
    • 取值范围: 0 ~ 65535 的整数
    • 一台计算机上的网络应用所使用的端口不会重复
    • 通常 0 ~ 1023 的端口会被一些有名的程序或者系统服务占用,个人一般使用 > 1024的端口

服务端与客户端

  • 服务端(Server):服务端是为客户端服务的,服务的内容诸如向客户端提供资源,保存客户端数据,处理客户端请求等。

  • 客户端(Client) :也称为用户端,是指与服务端相对应,为客户提供一定应用功能的程序,我们平时使用的手机或者电脑上的程序基本都是客户端程序。

UDP 传输方法

套接字简介

  • 套接字(Socket): 实现网络编程进行数据传输的一种技术手段,网络上各种各样的网络服务大多都是基于 Socket 来完成通信的。(注:socket是插座的意思,可以形象得理解为电脑上的网络插口)
  • Python套接字编程模块import socket

UDP套接字编程

  • 创建套接字sock = socket.socket(family,type)

    • family 网络地址类型 AF_INET表示ipv4,AF_INET6表示ipv6
    • type 套接字类型 SOCK_DGRAM 表示udp套接字 (也叫数据报套接字)
    • 返回一个套接字对象
  • 绑定本机网络地址sock.bind(ip,port)

    • 本地地址 :localhost , 127.0.0.1

    • 网络地址 : 例:172.40.91.185 (通过ifconfig查看,在没有分配公网ip时,本地网络地址是动态的。可以采用DDNS动态解析技术。)

    • 自动获取地址: ipv4使用 0.0.0.0,ipv6使用 ::

    • port为 接口

      注:箭头意为访问。

  • UDP 消息接收data,addr = sock.recvfrom(buffersize)

    • buffersize:每次(每包)最多接收多少字节
    • data 接收到的内容
    • addr 消息发送方地址
  • UDP 消息发送n = sock.sendto(data,addr)

    • data 发送的内容 bytes格式
    • addr 目标地址
    • 返回值:发送的字节数
  • 关闭套接字sock.close()

  • 服务端客户端流程

UDP套接字特点

  • 可能会出现数据丢失的情况,不保证可靠
  • 传输过程简单,实现容易
  • 数据以数据包形式表达传输
  • 数据传输效率较高

TCP 传输方法

TCP传输特点

  • 面向连接的传输服务
    • 传输特征 :提供了可靠的数据传输,可靠性指数据传输过程中无丢失,无失序,无差错,无重复。
    • 可靠性保障机制(都是操作系统网络服务自动帮应用完成的):
      • 在通信前需要建立数据连接
      • 确认应答机制
      • 通信结束要正常断开连接
  • 三次握手(建立连接)
    • 客户端向服务器发送消息报文请求连接
    • 服务器收到请求后,回复报文确定可以连接
    • 客户端收到回复,发送最终报文连接建立

  • 四次挥手(断开连接)
    • 主动方发送报文请求断开连接
    • 被动方收到请求后,立即回复,表示准备断开
    • 被动方准备就绪,再次发送报文表示可以断开
    • 主动方收到确定,发送最终报文完成断开

TCP服务端

  • 创建套接字
1
2
3
4
5
sock=socket.socket(family,type)
功能:创建套接字
参数:family 网络地址类型 AF_INET表示ipv4
type 套接字类型 SOCK_STREAM 表示tcp套接字 (也叫流式套接字)
返回值: 套接字对象
  • 绑定地址 (与udp套接字相同)

  • 设置监听

1
2
3
sock.listen(n)
功能 : 将套接字设置为监听套接字,确定监听队列大小
参数 : 监听队列大小

  • 处理客户端连接请求
1
2
3
4
conn,addr = sockfd.accept()
功能: 阻塞等待处理客户端请求
返回值: conn 客户端连接套接字
addr 连接的客户端地址
  • 消息收发
1
2
3
4
5
6
7
8
9
data = conn.recv(buffersize)
功能 : 接受客户端消息
参数 :每次最多接收消息的大小
返回值: 接收到的内容

n = conn.send(data)
功能 : 发送消息
参数 :要发送的内容 bytes格式
返回值: 发送的字节数
  • 关闭套接字 (与udp套接字相同)

TCP客户端

  • 创建TCP套接字
  • 请求连接
1
2
3
sock.connect(server_addr)
功能:连接服务器
参数:元组 服务器地址
  • 收发消息:防止两端都阻塞,服务器和客户端的 recv send 要配合

  • 关闭套接字

TCP套接字细节

  • tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
  • tcp连接中如果一端已经不存在,仍然试图通过send向其发送数据则会产生BrokenPipeError
  • 一个服务端可以同时连接多个客户端,也能够重复被连接

tcp粘包问题

  • 产生原因
    • 为了解决数据再传输过程中可能产生的速度不协调问题,操作系统设置了缓冲区
    • 实际网络工作过程比较复杂,导致消息收发速度不一致
    • tcp以字节流方式进行数据传输,在接收时不区分消息边界
  • 带来的影响
    • 如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。
  • 处理方法
    • 消息格式化处理,如人为的添加消息边界,用作消息之间的分割
    • 控制发送的速度

TCP与UDP对比

分类 TCP UDP
传输特征 提供可靠的数据传输 不保证传输的可靠性
传输数据处理为字节流 处理为数据包形式
传输需要建立连接才能进行数据传,效率相对较低 UDP 比较自由,无需连接,效率较高
套接字编程区别 会有粘包 有消息边界不会粘包
 依赖 listen accept 建立连接才能收发消息 不需要 listen accept
使用 send,recv 收发消息 使用 sendto,recvfrom
使用场景 适合对准确性要求高,传输数据较大的场景 适合对可靠性要求没有那么高,传输方式比较自由的场景
文件传输:如下载电影,访问网页,上传照片。邮件收发,点对点数据传输:如点对点聊天,登录请求,远程访问,发红包 视频流的传输: 如部分直播,视频聊天等,广播:如网络广播,群发消息,实时传输:如游戏画面
在一个大型的项目中,可能既涉及到 TCP 网络又有 UDP 网络

数据传输过程

传输流程

  • 发送端由应用程序发送消息,逐层添加首部信息,最终在物理层发送消息包。
  • 发送的消息经过多个节点(交换机,路由器)传输,最终到达目标主机。
  • 目标主机由物理层逐层解析首部消息包,最终到应用程序呈现消息。

TCP协议首部信息

  • 源端口和目的端口 各占2个字节,分别写入源端口和目的端口。
  • 序号 占4字节。TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。例如,一报文段的序号是301,而接待的数据共有100字节。这就表明本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。
  • 确认号 占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。
  • 确认ACK(ACKnowledgment) 仅当ACK = 1时确认号字段才有效,当ACK = 0时确认号无效。TCP规定,在连接建立后所有的传送的报文段都必须把ACK置为1。
  • 同步SYN(SYNchronization) 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1,因此SYN置为1就表示这是一个连接请求或连接接受报文。
  • 终止FIN(FINis,意思是“完”“终”) 用来释放一个连接。当FIN=1时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。