首页 > 其他分享 >总结6

总结6

时间:2022-11-20 20:59:13浏览次数:35  
标签:总结 __ 队列 print 进程 服务端 客户端

周结

目录

  • 软件开发结构
  • 网络编程发展史
  • QSI七层协议
  • 传输层主要协议
  • socket模块
  • 粘包现象
  • UDP协议
  • 操作系统发展史
  • 并发编程
  • 进程理论
  • 进程的并行与并发
  • 同步与异步
  • 创建进程的多种方式
  • 进程间的数据隔离
  • IPC机制 消息队列
  • 消费者模型

软件开发架构

C/S架构

client:客户端 即将要去消费的客人

server:服务端 给客人提供服务的店 店要具备:24小时不间断提供服务 固定的地址 能够服务多个客人

我们使用计算机下载下来的一个个app本质就是个大互联网公司的客户端软件 通过这些客户端软件就可以体验到各个互联网公司给我们提供到的服务

能够高度化定制

B/S架构

browser:浏览器

server:服务器/端

浏览器可以从当所有的服务端的客户端

B/S架构本身还是C/S架构

无法高度定制化

网络编程发展史

什么是网络编程:

基于网络编写代码 能够实现数据的远程交互

网络编程必备条件:物理连接介质 但光有物理链接介质还不够 还需要统一的语言:互联网协议

互联网OSI七层协议

OSI七层协议:规定了所有的计算机在远程数据交互的时候必须经过相同的处理流程、在制造过程中必须拥有相同的硬件

应用层
表示层
会话层
传输层
网络层
数据链路层
物理连接层
'''常见的是整合之后五层或者四层'''
应用层
传输层
网络层
数据链路层
物理连接层

应用层
传输层
网络层
网络接口层
'''
接收网络消息 数据是由下而上传递
发送网络消息 数据是由上而下传递
'''

物理连接层

主要用于确保计算机之间的物理链接介质 接收数据(bytes类型、二进制) 比如规定了网线材质 网口设计

数据链路层

电信号的分组方式(NF)基于物理链接层接收到一串二进制数

以太网协议

规定了计算机在出厂的时候必须都有一块网卡 12位16进制数 该数字也称为:以太网地址/MAC地址 也称物理地址

交换机:让连接的多台计算机之间彼此互联 由交换机组成的网络叫局域网

广播:首次查找接入的同一个交换机的其他计算机 需要朝计算机交换机里面吼一嗓子 在交换机里所有的计算机都可以接受到这个消息

单播:首次被查找的计算机回应查找它的计算机并附带自己的mac地址

广播风暴:接入同一台交换机的多台计算机同时发广播

局域网:可以简单的理解为有单个交换机组成的网络 在局域网可以直接使用mac地址通信

广域网:可以简单的理解为范围更大的局域网

互联网:所有的局域网、广域网连接到一起形成的网络

路由器:不同的局域网计算机之间是无法直接实现交互的 需要路由器连接

网络层

路由器实现跨局域网交互 将局域网彼此连接起来并支持数据交互

互联网其实可以看成是由多个局域网连接在一起

IP协议

规定了所有接入互联网的计算机都必须有一个IP地址 且是动态分配的 取决于所接的网线 你换根网线IP地址也变了

分 IPV4:点分十进制 0.0.0.0

IPV6:能够给地球上的每一粒沙分一个IP地址

arp协议:处于数据链路层 可以把IP协议转成mac地址 通过IP地址动态解析到使用者的mac地址

传输层

PORT协议(端口协议):计算机通过端口号管理正在运行的诸多应用程序

端口号的范围、端口号动态分配

范围:

0-65535:一台计算机最多同时运行65535 个程序

1-1024:系统经常使用的端口号

1024-8000:常用软件端口号

而我们写项目用8000之后的

动态分分配:

同一时间同一台计算机上面端口号只能给一个应用程序用

端口号是动态分配的

URl本质

网址的本质是IP和PORT组成的

IP地址:用于标识全世界独一无二的一台接入互联网的计算机

PORT号:表示一台计算机上面的某一台计算机上面的某一个应用

DNS域名解析

网址www.baidu.com其实就是IP + PORT也称域名

传输层主要协议

TCP协议

也称流式协议、可靠协议(数据不容易丢失)

三次握手:

1.客户端向服务端发送syn建立连接请求

2.服务端向客户端发送ark同意建立连接 此时客户端向服务端的单向通信管道建立

3.服务端也向客户端发送syn建立连接请求

4.客户端向服务端发送ark同意建立连接 这时服务端向客户端的单向通信管道建立

第三四步是可以整合到一起 就是两条信息一起发了 这就是三次握手建连接

也称为TCP的反馈机制 双方都有一个确认

四次挥手:

1.客户端向服务端发送syn断开连接请求

2.服务端向客户端发送ark同意连接断开 这时服务端就有一个time_wait检查自身是否还有数据没有发送完 检查没有了才会往下执行

3.服务端向客户端发送syn断开连接请求

4.客户端向服务端发送ark同意断开连接

洪水攻击

在同一时间有大量客户端请求建立连接 会导致服务端处于SYN_RCVD状态针对这种状态可以建立半连接池

UDP协议

丢包协议、不可靠协议 彼此之间不做任何的链接

传输速度快但可能会导致数据的丢失

socket模块

为操作OSI七层协议提供了快捷方式 不需要自己处理一遍

服务端
import socket
p1 = socket.socket()  # 括号内不填写默认就是TCP协议
p1.bind(('127.0.0.1', 8080))  回环地址 也只有自己电脑能够访问
p1.listen(5)  设立半连接池
sock, addr = p1.accept()  返回的是socket addr 三次握手分别指双向通道 及客户端地址
data = sock.recv(1024) 接收客户端发送过来的消息 1024字节 多了就抛弃
sock.send('发什么东西的是二进制'.encode('utf8'))  注意发送和接受的都是bytes类型 要对输入进行转码
socket.close() 关闭双向通道
p1.close() 关闭服务端
客户端
import socket
p1 = socket.socket() 生成协议
p1.connect(('127.0.0.1', 8080))
p1.send('直接发消息也得编译成二进制形式'.encode('utf8'))
data = p1.recv(1024)
p1.close() 断开与服务端的链接

半连接池

当有多个客户端来连接情况下 可以设置等待数量

粘包现象

粘包现象产生在TCP协议的通信中

服务端与客户端各连续执行接收与发送三次

服务端就一次性接收到了客户端的三次消息 称为粘包

原因:不知道每次的数据有多大、TCP协议也称为流式协议 数据象流水一样绵绵不绝

struct模块

把一个类型转成固定长度的bytes类型

import struct
res = '你好 请问你是谁呀'
print(len(res.encode('utf8')))  # 25
info = struct.pack('i', len(res.encode('utf8')))  # 将数据打包成固定的长度 i是固定的打包模式
print(info)  # b'\x19\x00\x00\x00'
print(len(info))  # 打包之后长度为(bytes)   4           报头

real_len = struct.unpack('i', info)
print(real_len)  # 根据固定长度的报头 解析出真实数据的长度 (25,)
print(real_len[0])  #25

粘包问题的终极解决方案

客户端:

1.制作一个真实数据相关的字典

2.将字典序列化并编码统计长度

3.利用struct模块对上述长度打包处理

4.直接发送打包之后的数据

5.再发送字典数据

6.最后发送真实数据

服务端:

1.接收固定长度的报头

2.利用struct模块反向解析出字典数据的长度

3.接收字典数据并处理成字典、

4.根据字典中的信息接收真实数据

操作系统的发展史

1.穿孔卡片

2.联机批处理

3.脱机批处理

单道技术

所有的程序排队执行

多道技术

饭店中只有一个服务员 同时服务 七八桌客人 且还让七八桌的的客人感觉都在服务他们 拿菜单让客人看!客人看的时候 去给别人点菜!只要有空闲 就立即切换到其他桌 如此往复

进程理论

程序:一堆死的代码(还没有被运行起来)

进程:正在运行的程序(被运行起来了)

进程的算法调度

先来先服务(FCFS):对短作业不友好

短作业优先(SJ/PF):对长作业不友好

时间片轮转法+多级反馈队列

时间片轮转:将CPU的时间划分为很多片 让每一个进程都能够分到运行的时间 比如5s的时间 划分为5个时间片都为1秒 先给每个进程用1秒 保证程序运行起来

多级反馈队列:对于使用过多个1秒时间片 但是未执行完的程序 将其放入一个新的队列 这个队列里可能每次给你分配2s的cpu使用权限 如果还没执行完的话再换下一个队列 在发5s的时间 以此类推

进程的三状态

就绪态:所有的进程在被CPU执行之前都必须进入就绪等待

运行态:CPU正在执行

阻塞态:进程运行过程中出现了IO操作

进程的并行与并发

并行:多个进程同时执行 必须要有多个CPU参与 两个人比赛赛跑 谁也不让谁

并发:多个进程看上去象同时执行 单个CPU可以实现 多个CPU也可以实现 一个服务员服务多个客人

同步与异步

同步:提交任务完后原地等待结果 期间不做任何事

异步:提交任务之后不愿原地等待任务的返回结果 直接去做其他事 等有结果了自动通知

阻塞与非阻塞

用来表达任务的执行状态

阻塞:程序处于阻塞态

非阻塞态:程序就绪态、运行态

创建进程的多种方式

multiprocessing模块之process

不同操作系统中创建进程原理不一样
	Windows:已导入模块的形式创建进程 (需要使用if __name__ == 'main')
	linux/mac:已拷贝的形式创建进程(复制的时候不包含创建进程的代码)
'''方式一'''
import time
from multiprocessing import Process

def task():
    print('子进程开始执行')
    time.sleep(3)
    print('子进程执行结束')


if __name__ == '__main__':
    p = Process(target=task)
    print(p, type(p))  # <Process(Process-1, initial)> <class 'multiprocessing.context.Process'>
    p.start()
# 用Process创建一个子进程对象 然后调用子进程对象的start()方法运行子进程

# 给子进程传参
import time
from multiprocessing import Process

def task1(a,b):
    time.sleep(3)
    print(a,b)

def task2(a,b):
    time.sleep(3)
    print(a,b)

if __name__ == '__main__':

    p1 = Process(target=task1, args=('cloud','alice'))  # 位置参数
    p2 = Process(target=task2, kwargs={'a':'cloud','b':'alice'})  # 关键字参数
    p1.start()
    p2.start()
    
'''方式二'''
import time
from multiprocessing import Process

class MyProcess(Process):
    def run(self):
        print('run is running')
        time.sleep(3)
        print('run is over')

if __name__ == '__main__':
    obj = MyProcess()  # 产生进程对象
    obj.start()  # 此时就会开一个子进程 子进程会去运行类中的run方法
    print('主')
# 给子进程传参
from multiprocessing import Process
import time


class MyProcess(Process):
    def __init__(self, name, age):  # 重写__init__方法
        super().__init__()  # 这里init不传参是因为 父类init里面的形参全是默认参数
        self.name = name  # 这里的self是进程对象
        self.age = age  # 给新产生的进程对象新增两个对象独有的属性name、age
                        # 备忘:__new__产生新对象

    def run(self):
        print('run is running', self.name, self.age)  # 使用对象中的属性
        time.sleep(3)
        print('run is over', self.name, self.age)


if __name__ == '__main__':
    obj = MyProcess('cloud', 18)
    obj.start()
    print('主')
    
join 方法
让主进程代码等待子进程代码结束之后再执行 这样主进程会停留在join方法处 主进程join方法下面的代码不会执行 直到子进程运行结束
terminate 方法
终止子进程 跟start一样也是异步操作
is_alive()  方法
判断子进程是否存活着

IPC机制 消息队列

IPC的概念:实现进程间通信

消息队列:消息队列可以理解成一个公共存数据的地方 所有的进程都可以存取

multiprocessing模块之Queue

from multiprocessing import Queue
# 1.产生消息队列q
q = Queue(3)  # 括号内可以指定存储数据的个数

使用get从队列中获取值 使用put往队列添加值 符合先进先出

当队列已满时,你使用put添加值
或者队列已空,你使用get获取值
都会导致当前进程阻塞,等待有别的进程往队列里添加/获取值


full() empty()
full 用于判断队列是否为满。
但有些需要注意:
1.判断的是当前进程的队列
2.判断的是执行full()这行代码这个瞬时时间下,队列的状态是否为满
empty 与 full 相反 判断的是队列是否为空

get_nowait()
这个方法如他的名字,如果获取不到队列的值,就马上抛出异常。

消息队列实现子进程消息传递
from multiprocessing import Process, Queue

def product(q):
    q.put('子进程p添加的数据')

def consumer(q):
    print('子进程获取队列中的数据', q.get())

if __name__ == '__main__':
    q = Queue()
    # 主进程往队列中添加数据
    # q.put('我是主进程添加的数据')
    p1 = Process(target=consumer, args=(q,))
    p2 = Process(target=product, args=(q,))
    p1.start()
    p2.start()
    print('主')
'''
consumer进程在消息队列没有数据的时候 这个进程会等待product进程往Queue放东西
'''

消费者模型

生产者:负责生产数据的人

消费者:负责处理数据的人

该模型除了有生产者和消费者之外必须有消息队列(只有能够提供数据保存服务和提供取服务的理论上都可以)

标签:总结,__,队列,print,进程,服务端,客户端
From: https://www.cnblogs.com/xiao-fu-zi/p/16909471.html

相关文章