Python笔记——网络编程

网络编程基础

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

OSI七层模型

制定组织: ISO(国际标准化组织)
作用:使网络通信工作流程标准化
应用层 : 提供用户服务,具体功能有应用程序实现
表示层 : 数据的压缩优化加密
会话层 : 建立用户级的连接,选择适当的传输服务
传输层 : 提供传输服务
网络层 : 路由选择,网络互联
链路层 : 进行数据交换,控制具体数据的发送
物理层 : 提供数据传输的硬件保证,网卡接口,传输介质
优点

  1. 建立了统一的工作流程
  2. 分部清晰,各司其职,每个步骤分工明确
  3. 降低了各个模块之间的耦合度,便于开发
四层模型(TCP/IP模型)

背景 : 实际工作中工程师无法完全按照七层模型要求操作,逐渐演化为更符合实际情况的四层

在这里插入图片描述

数据传输过程
  1. 发送端由应用程序发送消息,逐层添加首部信息,最终在物理层发送消息包。
  2. 发送的消息经过多个节点(交换机,路由器)传输,最终到达目标主机。
  3. 目标主机由物理层逐层解析首部消息包,最终到应用程序呈现消息。
    在这里插入图片描述

网络协议

在网络数据传输中,都遵循的规定,包括建立什么样的数据结构,什么样的特殊标志等。

网络地址

  • IP地址
    功能:确定一台主机的网络路由位置
    结构
    IPv4 点分十进制表示 172.40.91.185 每部分取值范围0–255
    IPv6 128位 扩大了地址范围
    查看本机网络地址命令: ifconfig
    测试和某个主机是否联通:ping [ip]
  • 端口号(port)
    作用:端口是网络地址的一部分,用于区分主机上不同的网络应用程序。
    特点:一个系统中的应用监听端口不能重复
    取值范围: 1 – 65535
    1–1023 系统应用或者大众程序监听端口
    1024–65535 自用端口

传输层服务

面向连接的传输服务(基于TCP协议的数据传输)
  1. 传输特征 : 提供了可靠的数据传输,可靠性指数据传输过程中无丢失,无失序,无差错,无重
    复。
  2. 实现手段 : 在通信前需要建立数据连接,通信结束要正常断开连接。

三次握手(建立连接)

  1. 客户端向服务器发送消息报文请求连接
  2. 服务器收到请求后,回复报文确定可以连接
  3. 客户端收到回复,发送最终报文连接建立
    在这里插入图片描述
    四次挥手(断开连接)
    1. 主动方发送报文请求断开连接
    2. 被动方收到请求后,立即回复,表示准备断开
    3. 被动方准备就绪,再次发送报文表示可以断开
    4. 主动方收到确定,发送最终报文完成断开
      在这里插入图片描述
      适用情况 : 对数据传输准确性有明确要求,传数文件较大,需要确保可靠性的情况。比如:网页获取,文件下载,邮件收发。
面向无连接的传输服务(基于UDP协议的数据传输)
  1. 传输特点 : 不保证传输的可靠性,传输过程没有连接和断开,数据收发自由随意。
  2. 适用情况 : 网络较差,对传输可靠性要求不高。比如:网络视频,群聊,广播
socket套接字编程
套接字介绍
  1. 套接字 : 实现网络编程进行数据传输的一种技术手段
  2. Python实现套接字编程:import socket
  3. 套接字分类
    流式套接字(SOCK_STREAM): 以字节流方式传输数据,实现tcp网络传输方案。(面向连接–tcp协议–可靠的–流式套接字)
    数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输方案。(无连接–udp协议–不可靠–数据报套接字)
tcp套接字编程
服务端流程
  1. 创建套接字
    sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
    功能:创建套接字
    参数: socket_family 网络地址类型 AF_INET表示ipv4
    socket_type 套接字类型 SOCK_STREAM(流式) SOCK_DGRAM(数据报)
    proto 通常为0 选择子协议
    返回值: 套接字对象
  2. 绑定地址
    本地地址 : ‘localhost’ , ‘127.0.0.1’
    网络地址 : ‘172.40.91.185’
    自动获取地址: ‘0.0.0.0’
    sockfd.bind(addr)
    功能: 绑定本机网络地址
    参数: 二元元组 (ip,port)
    (‘0.0.0.0’,8888)
  3. 设置监听
    sockfd.listen(n)
    功能 : 将套接字设置为监听套接字,确定监听队列大小
    参数 : 监听队列大小
  4. 等待处理客户端连接请求
    connfd,addr = sockfd.accept()
    功能: 阻塞等待处理客户端请求
    返回值: connfd 客户端连接套接字
    addr 连接的客户端地址
  5. 消息收发
    data = connfd.recv(buffersize)
    功能 : 接受客户端消息
    参数 :每次最多接收消息的大小
    返回值: 接收到的内容
    n = connfd.send(data)
    功能 : 发送消息
    参数 :要发送的内容 bytes格式
    返回值: 发送的字节数
  6. 关闭套接字
    sockfd.close()
    功能:关闭套接字
"""
tcp服务端流程:重点代码
"""
import socket
# 创建tcp套接字对象
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定地址
sockfd.bind(('127.0.0.1', 9988))
# 设置监听套接字
sockfd.listen(3)
# 处理客户端连接
connfd, addr = sockfd.accept()
# 收发消息(网络传输数据用字节串)
data = connfd.recv(1024)
n = connfd.send(b'Thanks')
# 关闭套接字
connfd.close()
sockfd.close()
客户端流程
  1. 创建套接字
    注意:只有相同类型的套接字才能进行通信
  2. 请求连接
    sockfd.connect(server_addr)
    功能:连接服务器
    参数:元组 服务器地址
  3. 收发消息
    注意: 防止两端都阻塞,recv send要配合
    (服务端先收后发,服务端先发后收)
  4. 关闭套接字
"""
tcp客户端流程
"""
from socket import *
# 服务器地址
server_addr = ('127.0.0.1', 9988)
# 创建tcp套接字
sockfd = socket()  # 默认值就是tcp套接字
# 连接服务器
sockfd.connect(server_addr)
# 发送接收消息
data = input(">>")
sockfd.send(data.encode())
data = sockfd.recv(1024)
print("From server:", data.decode())# 打印收到的消息转化为字符转格式
# 关闭套接字
sockfd.close()
tcp 套接字数据传输特点
  • tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
  • tcp连接中如果一端已经不存在,仍然试图通过send发送则会产生BrokenPipeError
  • 一个监听套接字可以同时连接多个客户端,也能够重复被连接
网络收发缓冲区
  1. 网络缓冲区有效的协调了消息的收发速度
  2. send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。
tcp粘包

原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。
影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。

处理方法

  1. 人为的添加消息边界
  2. 控制发送速度
UDP套接字编程
服务端流程
  1. 创建数据报套接字
    sockfd = socket(AF_INET,SOCK_DGRAM)
  2. 绑定地址
    sockfd.bind(addr)
  3. 消息收发
    data,addr = sockfd.recvfrom(buffersize)
    功能: 接收UDP消息
    参数: 每次最多接收多少字节
    返回值: data 接收到的内容
    addr 消息发送方地址
    n = sockfd.sendto(data,addr)
    功能: 发送UDP消息
    参数: data 发送的内容 bytes格式
    addr 目标地址
    返回值:发送的字节数
  4. 关闭套接字
    sockfd.close()
"""
udp服务端
"""
from socket import *
# 创建udp套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
# 绑定地址
server_addr = (("127.0.0.1", 9988))
sockfd.bind(server_addr)
# 收发数据
data, addr = sockfd.recvfrom(1024)
sockfd.sendto(b'Thanks', addr)
# 关闭套接字
sockfd.close()
客户端流程
  1. 创建套接字
  2. 收发消息
  3. 关闭套接字
"""
udp客户端
"""
from socket import *
# 创建udp套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
# 服务端地址
server_addr = ('127.0.0.1', 9988)
# 发收消息
deta = input(">>")
sockfd.sendto(deta.encode(), server_addr)
data, addr = sockfd.recvfrom(1024)
# 关闭套接字
sockfd.close()

总结 :tcp套接字和udp套接字编程区别

  1. 流式套接字是以字节流方式传输数据,数据报套接字以数据报形式传输
  2. tcp套接字会有粘包,udp套接字有消息边界不会粘包
  3. tcp套接字保证消息的完整性,udp套接字则不能
  4. tcp套接字依赖listen accept建立连接才能收发消息,udp套接字则不需要
  5. tcp套接字使用send,recv收发消息,udp套接字使用sendto,recvfrom
socket套接字常用属性

【1】 sockfd.type 套接字类型
【2】 sockfd.family 套接字地址类型
【3】 sockfd.getsockname() 获取套接字绑定地址
【4】 sockfd.fileno() 获取套接字的文件描述符
【5】 sockfd.getpeername() 获取连接套接字客户端地址
【6】 sockfd.setsockopt(level,option,value)
功能:设置套接字选项
参数: level 选项类别 SOL_SOCKET
option 具体选项内容
value 选项值
在这里插入图片描述

struct模块进行数据打包
  1. 原理: 将一组简单数据进行打包,转换为bytes格式发送。或者将一组bytes格式数据,进行解
    析。
  2. 接口使用
    Struct(fmt)
    功能: 生成结构化对象
    参数:fmt 定制的数据结构
    st.pack(v1,v2,v3…)
    功能: 将一组数据按照指定格式打包转换为bytes
    参数:要打包的数据
    返回值: bytes字节串
    st.unpack(bytes_data)
    功能: 将bytes字节串按照指定的格式解析
    参数: 要解析的字节串
    返回值: 解析后的内容
    struct.pack(fmt,v1,v2,v3…)
    struct.unpack(fmt,bytes_data)
    说明: 可以使用struct模块直接调用pack unpack。此时这两函数第一个参数传入fmt。其他用法
    功能相同
    在这里插入图片描述
import struct
st = struct.Struct("i10sfi")
data = st.pack(1, b"s", 0.1, 1)
data = st.unpack(data)
HTTP传输
HTTP协议 (超文本传输协议)
  1. 用途 : 网页获取,数据的传输
  2. 特点
    应用层协议,传输层使用tcp传输
    简单,灵活,很多语言都有HTTP专门接口
    无状态,协议不记录传输内容
    http1.1 支持持久连接,丰富了请求类型
  3. 网页请求过程
  • 客户端(浏览器)通过tcp传输,发送http请求给服务端
  • 服务端接收到http请求后进行解析
  • 服务端处理请求内容,组织响应内容
  • 服务端将响应内容以http响应格式发送给浏览器
  • 浏览器接收到响应内容,解析展示
    在这里插入图片描述
HTTP请求(request)
  • 请求行 : 具体的请求类别和请求内容
    GET / HTTP/1.1
    请求类别 请求内容 协议版本
    请求类别:每个请求类别表示要做不同的事情
    GET : 获取网络资源
    POST :提交一定的信息,得到反馈
    HEAD : 只获取网络资源的响应头
    PUT : 更新服务器资源
    DELETE : 删除服务器资源
    CONNECT
    TRACE : 测试
    OPTIONS : 获取服务器性能信息
  • 请求头:对请求的进一步解释和描述
    Accept-Encoding: gzip
  • 空行
  • 请求体: 请求参数或者提交内容
http响应(response)

响应格式:响应行,响应头,空行,响应体

  • 响应行 : 反馈基本的响应情况
    HTTP/1.1 200 OK
    版本信息 响应码 附加信息
    响应码 :
    1xx 提示信息,表示请求被接收
    2xx 响应成功
    3xx 响应需要进一步操作,重定向
    4xx 客户端错误
    5xx 服务器错误
  • 响应头:对响应内容的描述
    Content-Type: text/html
  • 响应体:响应的主体内容信息
import socket
# 创建tcp套接字对象
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定地址
sockfd.bind(('127.0.0.1', 9988))
# 设置监听套接字
sockfd.listen(3)
# 处理客户端连接
connfd, addr = sockfd.accept()
# 收发消息(网络传输数据用字节串)
data = connfd.recv(1024)
data = """HTTP/1.1 200 OK
Content-Type:text/html

Hello world
"""
n = connfd.send(data)
# 关闭套接字
connfd.close()
sockfd.close()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值