并发网络编程学习笔记(1)

1. 网络编程

  1. 网络基础
    • 网络功能:实现资源共享,信息快速传递
    • 网络通信标准
    • OSI 7层模型7应用层各层应用程序6表示层数据格式化、加解密、数据压缩与解压缩5会话层建立、管理、终止应用之间的会话连接4传输层提供端到端的数据服务(TCP/UDP)3网络层逻辑寻址、路由选择2数据链路层将分组数据封装成包1物理层在介质上传输比特;提供物理的规
    • 好处
      1. 建立了统一的通信标准
      2. 降低陈发难度,每层功能明确,各司其职
      3. 七层模型实际规定了每一层的任务,该完成什么事情
  2. TCP/IP模型
    • 七层模型过于理想,结构细节复杂
    • 在工程中应用实践难度大
    • 实际工作中以TCP/IP模型为工作标准流程OSI7层TCP/IP协议集Telnet,FTP,SMTP,DNS,HTTP等7应用层应用层6表示层应用层5会话层应用层4传输层传输层TCP、UDP3网络层网络层2数据链路层网络接口层1物理层网络接口层各种通信网络接口
  3. 应用工程师任务:编写应用功能,明确对方地址,选择传输服务
  4. 通信地址:
    • IP地址:即在网络中标识一台计算的地址编号
    • IP地址分类:
      • IPv4:分为4个部分,每个部分都是一个整数,取值从0-2255
      • IPv6:分为8个部分,每部分4个16进制数,如果出现连续0则用::省略中间的0
    • IP地址相关命令
      • Ifconfig 查看linux系统下计算机的IP地址
      • ping查看计算机的连通性
    • 公网IP和内网IP
      • 公网IP指的是连接到互联网的公共ip地址
      • 内网IP指的是局域网各范围内网络设备分配的IP地址
    • 端口号:网络地址的一部分,每个网络程序对应一个端口
      • 取值范围 :0-65535
      • 一台计算上网络所使用的端口不会重复
      • 通常0-1023端口会被一些系统服务占用
  5. 服务端与客户端
    • 服务端(server): 为客户端服务,服务内容如为客户端提供资源,保存客户端数据,处理客户端请求;
    • 客户端(client):也称用户端,为客户提供一定应用功能的程序。

2. UDP传输

  • 套接字: 实现网络编程进行数据传输的一种技术手段,网络上各种各样的网络服务大多都 是基于socket来完成通信的。
  • Python套接字编程模块:import socket
  • UDP套接字编程
    1. 创建套接字sockfd = socket.socket(socket_family,socket_type)
      功能:创建套接字
      参数:socket_family 网络地址类型 AF_INET表示ipv4
      socket_type 套接字类型 SOCK_DGRAM套接字(数据报套接字)
      返回:套接字对象
    2. 绑定地址本地地址:localhost,127.0.0.1
      网络地址:ifconfig查看
      自动获取地址:0.0.0.0

      sockfd.bind(addr)
      功能:绑定本机网络地址
      参数:二元元组(ip,port) 示例:("0.0.0.0",6666)
    3. 消息收发data,addr = sockfd.recvfrom(buffersize)
      功能:接收udp消息
      参数:每次最多接收多少字节
      返回值:data 接收到的内容
      addr 消息发送方地址

      msg = sockfd.sendto(data,addr)
      功能:发送UDP消息
      参数:data 发送的内容 bytes格式
          addr 目标地址
      返回值:发送的字节数
    4. 关闭套接字sokfd.close()
      功能:关闭套接字
  • UDP套接字特点
    • 可能会出现数据丢失的情况
    • 传输过程简单,易实现
    • 数据以数据包的形式表达传输
    • 数据传输效率高

3.TCP传输方法

  • TCP传输特点:
    • 面向连接传输服务
      • 传输特征:提供了可靠的数据传输,可靠性指数据过程中无丢失,无失序,无差错,无重复
      • 可靠性保障机制:
        • 在通信前需要建立数据连接
        • 确认应答机制
        • 通信结束要正常断开连接
    • 三次握手
      • 客户端服务器发送消息报文请求连接
      • 服务端收到请求后,回复报文确定可以连接
      • 客户端收到回复,发送最终报文连接建立
    • 四次挥手
      • 主动方发送报文请求断开连接
      • 被动方收到请求后,立即回复,表示准备断开
      • 被动方准备就绪,再次发送报文表示可以断开
      • 主动方收到确定,发送最终报文完成断开
  • TCP服务端
    1. 创建套接字sockfd = socket.socket(socket_family,socket_type)
      功能:创建套接字
      参数:socket_family 网络地址类型 AF_INET表示IPv4
      socket_type 套接字类型 SOCK_STRAM表示tcp套搠字(流式套接字)
      返回值:套接字对象
    1. 绑定地址本地地址:localhost,127.0.0.1
      网络地址:ifconfig查看
      自动获取地址:0.0.0.0

      sockfd.bind(addr)
      功能:绑定本机网络地址
      参数:二元元组(ip,port) 示例:("0.0.0.0",6666)
    1. 设置监听sockfd.listen(n)
      功能:将套接字设置为监听套接字,确定监听队列大小
      参数:监听队列大小
    1. 处理客户端连接请求connfd,addr = sockfd.accept()
      功能:阻塞等待客户端请求
      返回值:connfd 客户端连接套接字
      addr 连接的客户端地址
    1. 消息收发data = connfd.rev(buffersize)
      功能:接受客户端消息
      参数:每次最多接收消息的大小
      返回值:接收到的内容

      msg = connfd.send(data)
      功能:发送消息
      参数:要发送的内容 bytes格式
      返回值:发送的字节数
    1. 关闭套接字sokfd.close()
      功能:关闭套接字
  • TCP客户端
    1. 创建TCP套接字sockfd = socket.socket(socket_family,socket_type)
      功能:创建套接字
      参数:socket_family 网络地址类型 AF_INET表示IPv4
      socket_type 套接字类型 SOCK_STRAM表示tcp套搠字(流式套接字)
      返回值:套接字对象
    1. 请求连接sockfd.connect(server_addr)
      功能:连接服务器
      参数:元组 服务器地址
    1. 收发消息data = connfd.rev(buffersize)
      功能:接受客户端消息
      参数:每次最多接收消息的大小
      返回值:接收到的内容

      msg = connfd.send(data)
      功能:发送消息
      参数:要发送的内容 bytes格式
      返回值:发送的字节数

      # 注意:防止两端阻塞,recv send要配合
    1. 关闭套接字sokfd.close()
      功能:关闭套接字
  • TCP套接字细节
    1. tcp连接中当一端退出,另一端如果阻塞在recv,此时会立即返回一个空字串
    2. tcp连接中如果一端已经不存在,仍然试图通过send向其发送数据则会BrokenPipError
    3. 一个服务端可以同时连接多个客户端,也能够重复被连接
    4. TCP粘包问题
      • 产生原因
        • 为解决数据在传输过程中可能产生速度不协调问题,操作系统设备了缓冲区
        • 实际网络工作过程比较复杂,导致消息收发速度不一致
        • tcp字节流方式进行数据传输,在接收时不区分消息边界
      • 影响
        • 如果每次发送内容是一独立含义,需要接收端独立解析此时粘包有影响
      • 解决办法
        • 消息格式化处理,如人为添加消息边界,用于消息之间的分割
        • 控制发送速度

4. TCP与UDP对比

  1. 传输特征
    • TCP提供可靠的数据传输,UDP则不保证数据传输的可靠性
    • TCP传输数据处理为字节流,而UDP处理为数据包形式
    • TCP传输需要建立连接才能进行数据传,效率相对较低,UDP比较自由,无需连接,效率较高
  2. 套接字编程区别
    • 创建的套接字类型不同
    • TCP套接字会有粘包,UDP套接字有消息边界不会粘包
    • TCP套接字依赖listen accept建立连接才能收发消息,UDP套接字则不需要
    • TCP套接字使用send,recv收发消息,UDP套接字使用sendto,recvfrom
  3. 使用场景
    • TCP更适合对准确性要求高,传输数据较大的场景
      • 文件传输:如视频上、下载,网页访问,文件上传
      • 邮件收发
      • 点对点数据传输:聊天,登录,远程访问,红包
    • UDP适合对可靠性要求不太高,传输方式自由的场景
      • 视频流的传输:如直播,视频聊天
      • 广播:网络广播,群发消息
      • 实时传输:如游戏画面

5. 数据传输过程

  • 传输流程
    • 发送端由应用程序发送消息,逐层添加首部信息,最终在物理层发送消包
    • 发送消息经过多个节点(交换机、路由)传输,最终到达目标主机
    • 目标主机由物理逐层解析首部消息包,最终到应用程序呈现消息
  • TCP协调首部信息
    • 源端口、目标端口和占2字节
    • 序号 占4字节。TCP是面向字节流的,在一个TCP连接中传送的字节流中的第一个字节都 按顺序编号。
    • 确认号 占4字节。是期望收到对方下一个报文段的第一个数据字节的序号。
    • 确认ACK 仅当ACK=1时确认号字段才有效,当ACK=0时确认号无效。TCP规定,在连接建立后所有的传送的报文偳都必须把ACK置为1.
    • 同步SYN在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段。对方若同意建立连接,则应在响应的报文段中使用SYN=1和ACK=1,因此SYN置为1表示这是一个连接请求或连接接受授受报文。
    • 终止FIN(FINis,意思是“终”) 用来释放一个连接。当fin=1,表明此报文段的发送发的数据已民发送完毕,并要求释放运输连接。
# 示例代码 服务端
from socket import *
# 创建tcp套接字
tcp_socket = socket(AF_INET,SOCK_STREAM)
​
# 绑定地址
tcp_socket.bind(("0.0.0.0",3333))
​
# 设置为监听套接字
tcp_socket.listen(5)
​
# 等待客户端连接
while True:
  print("Waiting for connect...")
  connfd,addr = tcp_socket.accept()
  print("Connect from ",addr) 
  
​
  # 循环收发消息
  while True:
    data = connfd.recv(1024)
    if data == b"##":
      break
    print("收到:",data.decode())
    connfd.send(b"Thanks")
   connfd.close()
   
# 关闭套接字
tcp_socket.close()
版权声明:seasilo 发表于 2021-01-12 15:12:50。
转载请注明:并发网络编程学习笔记(1) | 海筒自习室

暂无评论

暂无评论...