TCP.UDP大致回顾
| TCP |
| 可靠协议 |
| 三次握手建立连接 |
| 1. 洪水攻击 |
| 2. 消息反馈 |
| 四次挥手断开连接 |
| 1.time_wait |
| |
| UDP |
| 不可靠协议 |
| """ |
| TCP类似于打电话 双方连接 |
| UDP类似于发短信 |
| """ |
应用层协议简介
socket套接字简介
| socket套接字作用于应用层于其他层之间 承上启下的类似于操作系统的作用 |
| |
socket基本使用
| import socket |
| socket.socket() 产生socket对象 |
| bind() 绑定地址 |
| listen() 半连接池 |
| accept() 等待客户端连接 |
| send() 发送消息 |
| recv() 接收消息 |
| connect() 链接服务端 |
socket代码优化
| 1.通信循环 |
| 2.链接循环 |
| 3.发送的消息不能为空、mac电脑反复重启服务端可能会报错地址错误、、服务端利用异常捕获增加健壮性 |
半连接池概念
| listen(5) 只能接收排队5位的意思 |
| 缓解服务端与客户端建立连接的压力 |
黏包现象
| 1.服务端连续执行三次recv |
| 2.客户端连续执行三次send |
| 问题:服务端一次性接收到了客户端三次的消息 该现象称为"黏包现象" |
| |
| |
| 黏包现象产生的原因 |
| 1.不知道每次的数据到底多大 |
| 2.TCP也称为流式协议:数据像流水一样绵绵不杜绝没有间隔(TCP会针对数量较小且发送间隔比较短的多条数据一次性合并打包发送) |
| |
| 避免黏包现象的核心思路\关键点 |
| 如何明确即将接收的数据具体由多大 |
| |
| ps:如何将长度变化的数据全部制作成固定长度的数据 |
struct模块
| import struct |
| |
| info = b'hello big baby' |
| print(len(info)) |
| res = struct.pack('i', len(info)) |
| print(len(res)) |
| |
| real_len = struct.unpack('i', res) |
| print(real_len) |
| |
| |
| |
| desc = b'hello my baby I will take you to play big ball' |
| print(len(desc)) |
| res1 = struct.pack('i', len(desc)) |
| print(len(res1)) |
| |
| real_len1 = struct.unpack('i', res1) |
| print(real_len1) |
| |
| |
| """ |
| 解决黏包问题初次版本 |
| 客户端 |
| 1.将真实数据转成bytes类型并计算长度 |
| 2.利用struct模块将真实长度制作一个固定长度的报头 |
| 3.将固定长度的报头先发送给服务端 服务端只需要在recv括号内填写固定长度的报头数字即可 |
| 4.然后再发送真实数据 |
| |
| |
| 服务端 |
| 1.服务端先接收固定长度的报头 |
| 2.利用struct模块反向解析出真实数据的长度 |
| 3.recv接收真实数据长度即可 |
| """ |
| |
| '''问题1:struct模块无法打包数据量较大的数据 就算换更大模块也不行''' |
| res = struct.pack('i', 1231234123) |
| print(res) |
| '''问题2:报头能否传递更多的信息 比如电影大小 电影名称 电影评价 电影简介''' |
| |
| '''终极解决方案:字典作为报头打包 效果更好 数字更小''' |
| |
| data_dict = { |
| 'file_name':'xxx老师教学.avi', |
| 'file_size':12312313212121231213, |
| 'file_info': '内容很精彩 千万不要错过', |
| 'file_desc': '一代神作 私人珍藏' |
| } |
| import json |
| data_json = json.dumps(data_dict) |
| print(len(data_json.encode('utf8'))) |
| res = struct.pack('i', len(data_json.encode('utf8'))) |
| |
| |
| |
| """ |
| 黏包问题终极方案 |
| 客户端 |
| 1.制作真实数据的信息字典(数据长度、数据简介、数据名称) |
| 2.利用struct模块制作字典的报头 |
| 3.发送固定长度的报头(解析出来时字典的长度) |
| 4.发送字典数据 |
| 5.发送真实数据 |
| 服务端 |
| 1.接收固定长度的字典报头 |
| 2.解析出字典的长度并接收 |
| 3.通过字典获取到真实数据的各项信息 |
| 4.接收真实数据长度 |
| """ |
黏包代码实战
| import socket |
| import struct |
| import json |
| |
| |
| server = socket.socket() |
| server.bind(('127.0.0.1', 8081)) |
| server.listen(5) |
| |
| sock,addr = server.accept() |
| |
| data_dict_head = sock.recv(4) |
| |
| data_dict_len = struct.unpack('i',data_dict_head)[0] |
| |
| data_dict_bytes = sock.recv(data_dict_len) |
| data_dict = json.loads(data_dict_bytes) |
| |
| |
| total_size = data_dict.get('file_size') |
| |
| |
| import socket |
| import os |
| import struct |
| import json |
| |
| client = socket.socket() |
| client.connect(('127.0.0.1', 8081)) |
| |
| '''任何文件都是下列思路 图片 视频 文本...''' |
| |
| file_size = os.path.getsize(r'D:\python代码\网络编程\xx老师合集.txt') |
| |
| data_dict = { |
| 'file_name': '有你好看.txt', |
| 'file_size': file_size, |
| 'file_desc': '内容很长 准备好吃喝 我觉得营养快线挺好喝', |
| 'file_info': '这是我的私人珍藏' |
| } |
| |
| data_dict_bytes = json.dumps(data_dict).encode('utf8') |
| data_dict_len = struct.pack('i', len(data_dict_bytes)) |
| |
| client.send(data_dict_len) |
| |
| client.send(data_dict_bytes) |
| |
| with open(r'D:\python代码\网络编程\xx老师合集.txt', 'rb') as f: |
| for line in f: |
| client.send(line) |
| import time |
| |
| time.sleep(10) |
UDP协议(了解)
| 1.UDP服务端和客户端'各自玩各自的' |
| 2.UDP不会出现多个消息发送合并 |
并发编程理论
| 理论非常多 实战很少 |
| 研究网络编程其实就是再研究计算机的底层原理及发展史 |
| """ |
| 计算机中真正干活的是CPU |
| """ |
| 操作系统发展史 |
| 1.穿孔卡片阶段 |
| 计算机很庞大 使用很麻烦 一次只能给一个人使用期间很多时候计算机都不工作 |
| 好处:程序员独占计算机 为所欲为 |
| 坏处:计算机利用率太低 浪费资源 |
| 2.联机批处理系统 |
| 提前使用磁带一次性录入多个程序员编写的程序 然后交给计算机执行 |
| CPU工作效率有所提升 不用反复等待程序录入 |
| 3.脱机批处理系统 |
| 极大的提升了CPU的利用率 |
| 总结:CPU提升利用率的过程 |
多道技术
| """ |
| 在学习并发编程的过程中 不做刻意提醒的情况下 默认一台计算机就一个CPU(只有一个干活的人) |
| """ |
| 单道技术 |
| 所有的程序排队执行 过程中不能重合 |
| 多道技术 |
| 利用空闲时间提前准备其他数据 最大化利用CPU 提升使用率 |
| |
| 多道技术详细 |
| 1.切换 |
| 计算机的CPU在两种情况下会切换(不让你用 给别人用) |
| 1.程序有IO操作 |
| 输入\输出操作 |
| input、time。sleep、read、write |
| |
| 2.程序长时间占用CPU |
| 我们得雨露均沾 让多个程序都能被CPU运行一下 |
| |
| |
| 2.保存状态 |
| CPU每次切换走之前都需要保存当前操作得状态 下次切换回来基于上次得进度继续执行 |
| |
| """ |
| 开了一家饭店 只有一个服务员 但是同时来了五桌客人 |
| 请问:如何让五桌客人都感觉到服务员在服务他们 |
| 让服务员化身闪电侠 只要有客户停顿 就可以切换到其他桌 如此往复 |
| """ |
进程理论
| 进程与程序的区别 |
| 程序:一堆死代码(还没有运行起来) |
| 进程:正在运行的程序(被运行起来了) |
| |
| 进程的调度算法(重要) |
| 1.FCFS(先来先服务) |
| 对短作业不友好 |
| 2.短作业优先调度 |
| 对长作业不友好 |
| 3.时间片轮转法+多级反馈队列(目前还在用) |
| 将时间均分 然后根据进程时间长短再分多个等级 |
| 等级越往下表示耗时越长 每次分到时间越多 但是优先级越低 |
进程的并行与并发
| 并行 |
| 多个进程同时执行 必须要有多个CPU参与 单个CPU无法实现并行 |
| 并发 |
| 多个进程看上去像同时执行 单个CPU可以实现 多个CPU肯定也可以 |
| |
| |
| 判断下列两句孰对孰错 |
| 我写的的程序很牛逼,运行起来之后可以实现14个亿的并行量 |
| 并行量必须要有对等的CPU才可以实现 |
| 我写的程序很牛逼,运行起来之后可以实现14个亿的并发量 |
| 合情合理 完全可以实现 以后我们的项目一般都会追求高并发 |
| 目前国内最牛逼的>>>:12306 |
进程的三状态
| 就绪态 |
| 所有的进程在被CPU执行之前都必须先进入就绪态等待 |
| |
| 运行态 |
| CPU正在执行 |
| 阻塞态 |
| |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构