首页 > 其他分享 >第八周总结

第八周总结

时间:2022-11-20 19:48:10浏览次数:36  
标签:总结 __ name 第八 print 进程 import 客户端

第八周总结

软件开发架构

1.C/S架构
    C:Client  客户端
    S:Server  服务端
    客户端指代的是手机端的APP和电脑上的各种软件,我们可以通过这些软件来进行各种各样的操作,聊天、看电影、玩游戏、购物等,但是这些操作是需要有数据来支撑的,所以我们手机电脑上的软件只是一个客户端,数据支撑位于网络另一端的服务器上,也就是服务端。
    作为服务端需要必备的几个条件:
        1.能够全天候不间断运行
        2.有一个固定的访问地址
        3.可以同时为多人提供服务
2.B/S架构
    B:Browser  浏览器
    S:Server  服务端
    这是基于浏览器来访问服务端,用浏览器充当客户端,就类似网页版的百度淘宝等

两者差别
    C/S架构
        不同的客户端由不同的公司独立开发,客户端功能高度定制化,但是客户顿需要下载才能使用
    B/S架构
        不用下载就可以直接访问,但是需要遵守浏览器的很多规则无法高度定制化

OSI七层协议

应用层
表示层
会话层
传输层
网络层 
数据链路层
物理连接层

这七层就是OSI七层协议,但是我们常见的是整合之后的四层或五层
应用层
传输层
网络层
数据链路层
物理连接层

# 接受网络消息,数据从下往上传;发送网络消息,数据从上往下传

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

物理链路层

用于确保计算机之间的物理连接介质,接收数据

数据链路层

1.规定了电信号的分组方式
2.以太网协议
    规定了计算机在出场的时候都必须有一块网卡,网卡上有一串数字,该数字就相当于计算机在网络中的唯一标识,就像人的身份证号一样
    该数字的特征是12位16进制数据,前六位位厂商编号,后六位为流水线号
    该数字也称为以太网地址/MAC地址

网络层

IP协议:
    规定了所有接入互联网的计算机都必须有一个IP地址
    MAC地址是唯一的,不可修改的
    IP地址是动态分配的,同一台机器不同地点不同场所下它的IP地址不同
IP地址特征:
    IPV4:点分十进制  0.0.0.0 —— 255.255.255.255
    IPV6:冒分十六进制,格式为X:X:X:X:X:X:X:X,其中每个X表示地址中的16b,以十六进制表示,其地址池数量号称可以为地球上每一粒沙子都分配一个IP地址
    

传输层

PORT协议,也称端口协议
    用来标识计算机上的某一个应用程序
    范围:0 - 65535
    特征:动态分配  0-1024 系统默认要用的  1024-8000  常见的软件端口号 
URL:统一资源定位符(网址)
    本质上是由IP和PORT组成的
IP+PORT:可以定位全世界唯一的一台计算机上面的某个应用程序
域名解析:将网址解析成IP+PORT
IP+PORT实际使用冒号链接 IP:PORT
我们访问百度网站通常都是实用网址访问,前面也说了网址实际是由IP和PORT组成的,那么我们当然可以通过IP+PORT来访问百度,只是这样太难记了,所以才有了域名

网络相关的专业名词

1.交换机
    能够将所有接入交换机的计算机彼此互联起来
2.广播
    首次查找接入同一个交换机的其它计算机,需要向交换机发送一个请求,该交换机内的所有计算机都能接收到这一请求
3.单播
    首次被查找的计算机回应查找它的计算机并附带自己的MAC地址
4.广播风暴
    接入同一台交换机的多台计算机同时发广播
5.局域网
    可以简单理解为一台交换机下面的所有计算机组成的网络
    在局域网中可以直接使用MAC地址通信
6.广域网
    就是范围更大的局域网,多台交换机组成的网络
7.互联网
    所有的局域网、广域网在一起组成的恶网络
8.路由器
    不同的局域网内的计算机是无法直接实现数据交互的,需要使用路由器连接

TCP与UDP协议

TCP与UDP都是用来规定通信方式的
1.TCP协议
    1.三次握手建链接(见图一)
    客户端各个状态:
        CLOSED状态:为关闭状态
        SYN_SENT状态:为请求连接状态, 当你要访问其它的计算机的服务时首先要发个同步信号给该端口,此时状态		为SYN_SENT,如果连接成功了就变为ESTABLISHED,此时SYN_SENT状态非常短暂。
        ESTABLISHED状态:连接成功

	服务端的各个状态:
        LISTENING状态:监听状态, State显示是LISTENING时表示处于侦听状态,就是说该端口是开放的,等待连			接,但还没有被连接。就像你房子的门已经敞开的,但还没有人进来。
        SYN-RCVD状态:收到和发送一个连接请求后等待对方对连接请求的确认。
        ESTABLISHED状态:连接成功
        
        TCP协议也称之为可靠协议(数据不容易丢失)
            TCP可靠不是因为有双通道,而是因为有反馈机制,给对方发送消息之后会保留一个副本,对方反馈消息收			到了删除副本,否则会在一定时间内一直发送
        洪水攻击
            同一时间有大量客户请求建立连接,导致服务器端一直处于SYN_RCVD状态
        服务端如何区分客户端建立连接的请求
            对请求做唯一标识
        
        2.四次挥手断链接(见图二)
        第一次挥手:
        客户端向服务器发送一个 FIN 数据包(FIN = 1,seq = u)主动断开连接,报文中会指定一个序列号,告诉         服务器:我要跟你断开连接了,不会再给你发数据了;
        客户端此时还是可以接收数据的,如果一直没有收到被动连接方的确认包,则可以重新发送这个包,此时客户端         处于 FIN_WAIT1 状态
	    第二次挥手:
        服务器收到 FIN 数据包之后,向客户端发送确认包(ACK = 1,ack = u + 1),把客户端的序列号值 + 1 作         为 ACK 报文的序列号值,表明已经收到客户端的报文了
        这是服务器在告诉客户端:我知道你要断开了,但是我还有数据没有发送完,等发送完了所有的数据就进行第三         次挥手
        此时服务端处于 CLOSE_WAIT 状态,客户端处于 FIN_WAIT2 状态
        第三次挥手:
        服务器向客户端发送FIN 数据包(FIN=1,seq = w),且指定一个序列号,以及确认包(ACK = 1, ack = u         + 1),用来停止向客户端发送数据
        这个动作是告诉客户端:我的数据也发送完了,不再给你发数据了
        此时服务端处于LAST_ACK状态,客户端处于TIME_WAIT状态
        第四次挥手:
        客户端收到 FIN数据包 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK         报文的序列号值
        此时客户端处于 TIME_WAIT 状态。
        需要过一了一定时间(2MSL)之后,客户端发送确认包(ACK = 1, ack = w + 1),此时客户端才会进入           CLOSED 状态,以确保发送方的ACK可以到达接收方,防止已失效连接请求报文段出现在此连接中。
        至此,完成四次挥手。
        
2.UDP协议
    也称之为数据报协议,不可靠协议
    它的工作原理就是直接向对方的地址发送数据,不管有没有建立链接,不管对方能不能收到

图一
image
图二
image

socket模块

给我们提供了一个模拟控制OSI七层协议的方法,快让我们可以基于网络编写一个进行数据交互的程序
socket也叫套接字
    基于文件类型的套接字家族(单机)
  	    AF_UNIX
    基于网络类型的套接字家族(联网)
  	    AF_INET

代码简介

需求:
    1.聊天内容自定义
    2.让聊天循环起来
    3.用户发送的消息不能为空
    4.服务端多次重启可能会报错
    5.客户端异常断开时如何让服务端继续服务其他客户端

服务端:
import socket

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
    sock, addr = server.accept()
    while True:
        try:
            data = sock.recv(1024)
            print(f'收到来自{addr}的消息:', data.decode('utf8'))
            msg = input('').strip()
            sock.send(f'回复:{msg}'.encode('utf8'))
        except BaseException:
            break
            
客户端:          
import socket

client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
    msg = input('请输入您想要发送给服务端的消息>>>:').strip()
    if len(msg) == 0:
        print('不能发送空消息')
        continue
    client.send(msg.encode('utf8'))
    data = client.recv(1024)
    print('来自于服务端发送过来的消息>>>:', data.decode('utf8'))

半连接池

server.listen(5)
当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题的情况下)
假设服务端只有一个人的情况下

在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可 

黏包现象

介绍

1.何为黏包现象
    黏包现象就是客户端连续多次执行send,服务端连续执行相同次数的recv想对应接收客户端发送过来的数据,但是服务端却一次性接受了客户端发来的数据,这就是黏包现象
2.黏包现象产生的原因
    1.每次发送的数据大小未知
    2.TCP流式协议,就是TCP会针对数据量较小且发送间隔较短的多条数据进行合并一次性打包发送
3.解决黏包问题的方法
    要知道每次发送的数据大小,并告诉服务端

struct模块

可以将数据打包成固定的长度,基于struct模块我们可以解决黏包问题
解决黏包问题流程
    客户端
        1.先将真实数据转成bytes类型并计算长度
        2.使用struct模块制作一个固定长度的报头
        3.将制作的固定长度报头发送给服务器
        4.最后再发送真实数据
    服务端
        1.先接受固定长度的报头
        2.使用struct模块反向解析出真实数据长度
        3.接收真实数据
        
代码
import struct

info = b'hello big baby'
print(len(info))  # 数据真实的长度(bytes)  14
res = struct.pack('i', len(info))  # 将数据打包成固定的长度 i是固定的打包模式
print(len(res))  # 打包之后长度为(bytes)   4           报头

real_len = struct.unpack('i', res)
print(real_len)  # (14,)             根据固定长度的报头 解析出真实数据的长度


desc = b'hello my baby I will take you to play big ball'
print(len(desc))  # 数据真实的长度(bytes)  46
res1 = struct.pack('i', len(desc))
print(len(res1))  # 打包之后长度为(bytes)  4           报头

real_len1 = struct.unpack('i', res1)  # 反向解析真实长度
print(real_len1)  # (46,)              根据固定长度的报头 解析出真实数据的长度

这样做确实可以解决黏包问题,但是有缺陷,因为struct模块无法打包数据量较大的数据,更换模式也不行、
struct.pack('i',1111111111111)
struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #这个是范围
这个时候我们可以使用字典作为报头打包(这也是黏包问题的终极解决方案)
data_dict = {
    'file_name': 'xxx.mp4',
    'file_size': 123132131232342342423423423423432423432,
    'file_info': '内容很精彩 千万不要错过',
    'file_desc': '一代神作 私人珍藏'
}
import json
data_json = json.dumps(data_dict)
print(len(data_json.encode('utf8')))  # 真实字典的长度  228
res = struct.pack('i', len(data_json.encode('utf8')))
print(len(res))
这个时候的流程是
客户端 
        1.制作真实数据的信息字典(数据长度、数据简介、数据名称)
        2.利用struct模块制作字典的报头
        3.发送固定长度的报头(解析出来是字典的长度)
        4.发送字典数据
        5.发送真实数据     
    服务端
        1.接收固定长度的字典报头
        2.解析出字典的长度并接收
        3.通过字典获取到真实数据的各项信息
        4.接收真实数据长度

并发编程理论

研究网络编程其实就是在研究计算机的底层原理及发展史
操作系统发展史
	1.穿孔卡片阶段
  	计算机很庞大 使用很麻烦 一次只能给一个人使用 期间很多时候计算机都不工作
    	好处:程序员独占计算机 为所欲为
  		坏处:计算机利用率太低 浪费资源
  2.联机批处理系统
  	提前使用磁带一次性录入多个程序员编写的程序 然后交给计算机执行
    	CPU工作效率有所提升 不用反复等待程序录入
	3.脱机批处理系统
  	极大地提升了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可以实现 多个CPU也可以
    可以支持多个人同时访问,只要CPU够强就可以一个CPU运行,当然多个CPU一起来也可以
    

进程的三状态

就绪态
	所有的进程在被CPU执行之前都必须先进入就绪态等待
运行态
	CPU正在执行
阻塞态
	进程运行过程中出现了IO操作 阻塞态无法直接进入运行态 需要先进入就绪态

image

任务的提交方式与执行状态

同步与异步

同步与异步是用来表达任务的提交方式
同步  就是提交完任务之后原地等待任务的返回结果,期间不做任何事
异步  就是提交完任务之后直接去做其他事,任务产生结果了自动通知

阻塞与非阻塞

用来表达任务的执行状态
阻塞  阻塞态
非阻塞  就绪态、运行态

综合使用

同步阻塞
异步阻塞
同步非阻塞
异步非阻塞

创建进程的多种方式

方式一: 直接定义函数
from multiprocessing import Process
import time
def task(name):
    print('task is running',name)
    time.sleep(3)
    print('task is over',name)
    
 if __name__ == '__main__':
    # p1 = Process(target=task, args=('jason',))  # 位置参数
    p1 = Process(target=task, kwargs={'name':'jason123'})  # 关键字参数
    p1.start()  # 异步 告诉操作系统创建一个新的进程 并在该进程中执行task函数
    print('主')
    
    
方式二: 利用类
from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self, name, age):
        super().__init__()
        self.name = name
        self.age = age
        
    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('jason', 123)
    obj.start()
    print('主')
    
    
# 创建进程需要使用到multiprocessing模块中的Process类,代码中创建进程使用start()

进程间数据隔离

同一台计算机上的多个进程数据是严格意义上的物理隔离
from multiprocessing import Process
import time

money = 1000


def task():
    global money
    money = 666
    print('子进程的task函数查看money', money)


if __name__ == '__main__':
    p1 = Process(target=task)
    p1.start()  # 创建子进程   子进程的task函数查看money 666
    time.sleep(3)  # 主进程代码等待3秒
    print(money)  # 主进程代码打印money   1000
 # 子进程与主进程不在一个名称空间

进程的join方法

from multiprocessing import Process
import time


def task(name, n):
    print('%s is running' % name)
    time.sleep(n)
    print('%s is over' % name)


if __name__ == '__main__':
    p1 = Process(target=task, args=('jason1', 1))
    p2 = Process(target=task, args=('jason2', 2))
    p3 = Process(target=task, args=('jason3', 3))
    # p.start()  # 异步
    '''主进程代码等待子进程代码运行结束再执行'''
    # p.join()
    # print('主')
    start_time = time.time()
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print(time.time() - start_time)  # 6秒多
    # join方法就是将进程的异步变为同步,主进程代码等子进程代码运行结束后再执行

IPC机制

IPC:进程间通信
消息队列:存储数据的地方 所有人都可以存 也都可以取

from multiprocessing import Queue

q = Queue(3)  # 括号内可以指定存储数据的个数
# 往消息队列中存放数据
q.put(111)
print(q.full())  # 判断消息队列是否已满
# 从消息队列中取出数据
print(q.get())
print(q.empty())  # 判断队列是否为空

# full() empty() 在多进程中都不能使用!!!

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('主')

生产者消费者模型

"""回想爬虫"""
生产者
	负责产生数据的'人'
消费者
	负责处理数据的'人'
    
该模型除了有生产者和消费者之外还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以)

进程对象的多种方法

1.如何查看进程号
	from multiprocessing import Process, current_process
 	current_process()
 	current_process().pid  
	import os
 	os.getpid()  # 查看当前进程号
  	os.getppid()  # 查看父进程号
2.终止进程
	p1.terminate()
	ps:计算机操作系统都有对应的命令可以直接杀死进程
3.判断进程是否存活
	p1.is_alive()
4.start()
5.join()

守护进程

守护进程会随着守护的进程结束而立刻结束
      
from multiprocessing import Process
import time


def task(name):
    print('德邦总管:%s' % name)
    time.sleep(3)
    print('德邦总管:%s' % name)


if __name__ == '__main__':
    p1 = Process(target=task, args=('大张红',))
    p1.daemon = True
    p1.start()
    time.sleep(1)
    print('恕瑞玛皇帝:小吴勇嗝屁了')

僵尸进程与孤儿进程

僵尸进程
	进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来
 	比如进程号、进程执行时间、进程消耗功率等给父进程查看
 	ps:所有的进程都会变成僵尸进程
孤儿进程
	子进程正常运行 父进程意外死亡 操作系统针对孤儿进程会派遣福利院管理

多进程数据错乱问题

模拟抢票软件

from multiprocessing import Process
import time
import json
import random


# 查票
def search(name):
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num')))


# 买票
def buy(name):
    # 再次确认票
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    # 模拟网络延迟
    time.sleep(random.randint(1, 3))
    # 判断是否有票 有就买
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'data.json', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print('%s买票成功' % name)
    else:
        print('%s很倒霉 没有抢到票' % name)


def run(name):
    search(name)
    buy(name)


if __name__ == '__main__':
    for i in range(10):
        p = Process(target=run, args=('用户%s'%i, ))
        p.start()
   
"""
多进程操作数据很可能会造成数据错乱>>>:互斥锁
	互斥锁
		将并发变成串行 牺牲了效率但是保障了数据的安全
"""

标签:总结,__,name,第八,print,进程,import,客户端
From: https://www.cnblogs.com/zyg111/p/16909291.html

相关文章

  • 2022-2023-1 20221329 《计算机基础和程序设计》第十二周学习总结
    班级链接:https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP作业要求:https://www.cnblogs.com/rocedu/p/9577842.html#WEEK12作业目标:学习《C语言程序设计》第11章......
  • 2022-2023-1 20221312 《计算机基础与程序设计》第十二周学习总结
    班级链接:首页-2022-2023-1-计算机基础与程序设计-北京电子科技学院-班级博客-博客园(cnblogs.com)作业要求:2022-2023-1《计算机基础与程序设计》教学进程-娄......
  • 2022-2023-1 20221311 《计算机基础与程序设计》第十二周学习总结
    班级链接:https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP作业要求:https://www.cnblogs.com/rocedu/p/9577842.html#WEEK08作业目标:作业目标:《C语言程序设计》第11......
  • 【博学谷学习记录】超强总结,用心分享 集合重要知识点。
    集合1.1常见的数据结构常见的数据结构有:数组、栈、队列、链表、树、散列、堆、图等。数组是最常用的数据结构,数组的特点是长度固定,数组的大小固......
  • 2022-2023-1 20221414《计算机基础和程序设计》第12周学习总结
    基本信息这个作业属于哪个课程2022-2023-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计第11周作业这个作业的目标c语言第10......
  • 第八周内容回顾
    目录一、软件开发架构二、网络编程三、OSI七层协议简介物理层数据链路层网络相关的一些名词网络层传输层传输层应用层四、socket模块创建服务端客户端五、黏包现象及解决方......
  • 【博学谷学习记录】超强总结,用心分享|moco
    一、介绍1、什么是mock1)mock就是对于一些难以构造的对象,使用虚拟的技术来实现测试的过程。2)mock测试:在测试过程中,对于某些不容易构造或者不容易获取的对象,可以用一个虚......
  • 11月18学习总结
    11月18学习总结一、软件开发目录1.软件开发框架软件开发框架:在编写项目之前需要遵循的代码层面上面的规范(运行流程,环节,步骤)2.软件开发框架的分类1.c/s框架client/......
  • 第八周总结
    目录软件开发架构网络编程前戏OSI七层协议简介OSI七层协议之物理连接层OSI七层协议之数据链路层OSI七层协议之网络层OSI七层协议之传输层传输层之TCP与UDP协议应用层socket......
  • 本周总结11.20
    周末总结1.软件开发架构2.网络编程3.OSI七层协议4.socket模块5.黏包现象6.并发编程理论7.多道技术8.进程理论9.创建进程的方式10.进程的join方式11.进程对象的......