文章目录
- 网络编程基础概念
-
- 第一个网络通信
- 协议概念
- udp
- tcp
-
- 初识
- tcp中的现象
- tcp文件传输
- 验证客户端的合法性
- socketserver
- 多线程
-
- 进程
-
- 1.概念
- 2.多进程实现一个并发的socket的server
- 3.开启进程的另一种方法
- 4.process类的其他方法
- 5.守护进程
- 6.锁
- 7.队列
-
- 生产者消费者模型
- 8.异步阻塞
-
- 生产者消费者模型
- 线程
-
- 1.threading模块
- 2.守护线程
- 3.线程锁
- 4.单例模式
- 5.递归锁和死锁
- 6.队列
- 7.池
- 协程
-
- 1.协程概述
- 数据库
-
- 1.初识
- 2.表操作
- 3.索引
- 4.pymysql模块
- 5.事务、锁
- web服务
-
- 1.初识http
- 2、web框架
网络编程基础概念
# 打基础
# 了解一些网络的基础知识
# 简单的了解一些底层的网络通信
# 网络的概念
# 基于原生的网络模块来实现通信
# 概念
# 不变的:mac地址 能够唯一表示你这台机器的
# 变化的:ip地址 能够更好地更方便的找到你的机器
# 局域网:网段 交换机 不能理解IP地址,只能理解mac地址
# 局域网和局域网之间通信了:
# 网管 路由器 可以理解IP地址
# IP地址
# 0.0.0.0-255.255.255.255
#
# 公网地址:需要我们申请购买的地址
# 内网地址:保留字段
# 192.168.0.0- 192.168.255.255 内网地址
# 172.16.0.0- 172.31.255.255 内网地址
# 10.0.0.0- 10.255.255.255 内网地址
# 特殊的ip地址:
# 127.0.0.1 本地回环地址 测试的时候用的
# 子网掩码也是一个ip地址,用来判断两台机器在不在一个局域网内
# ipv6 0:0:0:0:0:0-FFFFFF:FFFFFF:FFFFFF:FFFFFF:FFFFFF:FFFFFF:192.168.12.3
# ip/mac 确认机器的
# 端口 0-65535 确认机器上的具体应用
# 概念整理
# 局域网的概念
# 交换机
# 在同一个局域网内的机器有交换机负责通信
# 交换机只认识mac地址
# 可以完成广播 组播 单薄
# 单播 -- mac地址(在网卡上)
# 局域网之间通信
# 路由器
# 提供网关ip,同一个局域网的所有机器共享一个网关
# 我们不能访问除了本局域网之外的其他内网的ip地址
# 子网掩码
# 用来判断两台机器是不是在一个网段内
# ip地址:ipv4协议, ipv6协议
# mac地址:arp协议(通过ip找mac)
# 端口port:0-65535, 用来确认机器上的具体应用
# 网络开发结构
# C/S架构
# client客户端 我们用的 需要安装的
# server服务端
# B/S架构:百度,博客园
# browser浏览器
# server服务端
# C/S架构和B/S架构什么关系?
# B/S架构也是C/S架构中的一种
# C/S架构的好处;
# 可以离线使用/功能更完善/安全性更高
# B/S架构的好处:(发展的方向)
# 不用安装就可以使用
# 统一PC端用户的入口
#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
第一个网络通信
- 永远是服务端先启动,客户端才能启动
server端
import socket
sk = socket.socket()
sk.bind(('192.168.121.1', 9000)) # 绑定 ip + 端口
sk.listen() # 监听
conn, adder = sk.accept()
conn.send(b'hello') # 发送信息
msg = conn.recv(1024) # 接收的最大字节
print(msg)
conn.close()
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
client端
import socket
sk = socket.socket()
sk.connect(('192.168.121.1', 9000))
msg = sk.recv(1024)
print(msg)
sk.send(b'byebye')
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
协议概念
# 5层协议
# 应用层 python
# 传输层 port 四层路由器 (四层交换机)
# 网络层 ipv4 ipv6 路由器 (三层交换机)
# 数据链路层 mac arp协议 网卡 (二层交换机)
# 物理层
# 7层协议
# 应用层 (表示层 会话层)
# 传输层 port
# 网络层 ipv4 ipv6 路由器
# 数据链路层 mac arp协议 交换机
# 物理层
# tcp 和 udp
# tcp 打电话 - 线下缓存高强视频/qq远程控制/发邮件
# 需要先建立链接,然后才能通信
# 占用连接/可靠(消息不会丢失)/实时性高/慢
# 建立链接 - 三次握手
# 断开链接 - 四次握手
# 什么是三次握手?什么是四次握手?为什么握手是三次/四次?这个过程都传递了哪些信号
# udp 发短信 - 在线播放视频
# 不需要建立链接,就可以通信
# 不占用连接/不可靠(消息因为网络不稳定丢失)/快
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
udp
- server
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1', 8666))
while True:
msg, adder = sk.recvfrom(1024) # 接收 , adder为对方地址 ip+port
# if msg.decode('utf-8').lower() == 'q':
# print('会话结束')
# break
if msg.decode('utf-8').lower() == 'q':
continue
print(msg.decode('utf-8'))
send_msg = input('请输入:')
sk.sendto(send_msg.encode('utf-8'), adder)
# if send_msg.lower() == 'q':
# print('会话结束')
# break
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- client
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
server = ('127.0.0.1', 8666)
while True:
send_msg = input('请输入:')
sk.sendto(send_msg.encode('utf-8'), server) # 发送
if send_msg.lower() == 'q':
print('会话结束')
break
msg = sk.recv(1024).decode('utf-8') # 接收
if msg.lower() == 'q':
print('会话结束')
break
print(msg)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
tcp
初识
- server
import socket
sk = socket.socket()
sk.bind(('192.168.121.1', 9000)) # 申请操作系统的资源
sk.listen() # 监听
# while True: # 可以和多个客户端建立连接
# conn, adder = sk.accept() # conn里储存的是一个客户端和我server端连接信息
# conn.send(b'hello') # 发送信息
# msg = conn.recv(1024) # 接收的最大字节
# print(msg)
# conn.close() # 挥手 断开连接
conn, adder = sk.accept() # conn里储存的是一个客户端和我server端连接信息
while True:
send_msg = input('请输入:')
conn.send(send_msg.encode('utf-8')) # 发送信息
if send_msg.upper() == 'Q':
break
msg = conn.recv(1024).decode('utf-8') # 接收的最大字节
if msg.upper() == 'Q':
break
print(msg)
conn.close() # 挥手 断开连接
sk.close() # 归还申请的操作系统的资源
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- client
import socket
sk = socket.socket()
sk.connect(('192.168.121.1', 9000))
while True:
msg2 = sk.recv(1024).decode("utf-8")
if msg2.upper() == 'Q':
break
print(msg2)
send_msg = input("请输入:")
sk.send(send_msg.encode('utf-8'))
if send_msg.upper() == 'Q':
break
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
tcp中的现象
- 不知道对方传输的字节大小
- 使用struct模块,转换为4字节
-
- 转:struct.pack(‘i’, len(msg2))
-
- 现接收字节大小:le = sk.recv(4)
-
- 再转为原来字节:struct.unpack(‘i’, le)[0] (注意返回的是元组, 所以取第一个)
- 每条信息都要转
- server
import socket
import struct
sk = socket.socket()
sk.bind(('127.0.0.1', 8666)) # 地址绑定
sk.listen() # 监听
conn, adder = sk.accept() # 建立连接
msg1 = input(">>>").encode('utf-8')
msg2 = input('>>>').encode('utf-8')
# num1 = str(len(msg1)) # 不能超过 9999字节
# ret = num1.zfill(4) # 转为4位 用 0 补字节
blen = struct.pack('i', len(msg1)) # 可以把两个g的内容转化为4个字节
conn.send(blen) # 先发送传输的字节大小
conn.send(msg1)
blen = struct.pack('i', len(msg2)) # 可以把两个g的内容转化为4个字节
conn.send(blen) # 先发送传输的字节大小
conn.send(msg2)
conn.close()
sk.close()
# 粘包现象 只出现在tcp协议中,因为tcp协议 多条信息之间没有边界,并且还有一大堆优化算法
# 发送端:两条消息很短且发送的间隔很短
# 接收端:接收消息不及时
# 导致粘包问题的本质:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- client
import socket
import struct
sk = socket.socket()
sk.connect(('127.0.0.1', 8666))
le = sk.recv(4) # 先接收传输的字节大小
le = struct.unpack('i', le)[0] # 解字节 ,返回元组
msg1 = sk.recv(le).decode('utf-8')
print(msg1)
le = sk.recv(4) # 先接收传输的字节大小
le = struct.unpack('i', le)[0] # 解字节 ,返回元组
msg2 = sk.recv(le).decode('utf-8')
print(msg2)
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
struct模块
import struct
num = 1234568
num2 = 123
num3 = 8
ret = struct.pack('i', num) # 可以把两个g的内容转化为4个字节
print(len(ret))
de = struct.unpack('i', ret) # 解字节 返回元组
print(de)
ret = struct.pack('i', num2) # 可以把两个g的内容转化为4个字节
print(len(ret))
de = struct.unpack('i', ret) # 解字节 返回元组
print(de)
ret = struct.pack('i', num3) # 可以把两个g的内容转化为4个字节
print(len(ret))
de = struct.unpack('i', ret) # 解字节 返回元组
print(de)
-----------------------------
4
(1234568,)
4
(123,)
4
(8,)
-----------------------------
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
tcp文件传输
- server
import json
import socket
import struct
# 解决粘包问题
sk = socket.socket()
sk.bind(('127.0.0.1', 9696))
sk.listen()
conn, _ = sk.accept()
msg_len = conn.recv(4) # 接收四个字节
msg_len = struct.unpack('i', msg_len)[0] # 解字节,返回的值是元组,取第一个,就是原来的数据大小
msg = conn.recv(msg_len)
msg = json.loads(msg) # 加载msg
with open(msg['filename'], 'wb') as f: # msg['filename'] 文件名字
while msg['filesize'] > 0: # msg['filesize'] 文件大小
content = conn.recv(1024)
# 传输的过程中,接收的不一定是1024个字节,因为要过转建站交换机
msg['filesize'] -= len(content) # 收多少减多少
f.write(content)
conn.close()
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- client
import json
import socket
import os
import struct
# 发送
sk = socket.socket()
sk.connect(('127.0.0.1', 9696))
# 文件名
# 文件大小
abs_path = r'D:\PyCharmProject\python-核心编程\hehe'
filename = os.path.basename(abs_path) # 拿到文件名
filesize = os.path.getsize(abs_path) # 文件大小 xxx字节
dic = {'filename': filename, 'filesize': filesize}
str_dic = json.dumps(dic) # 将dic转为字符串json
b_dic = str_dic.encode('utf-8')
mlen = struct.pack('i', len(b_dic)) # 转化为四字节
sk.send(mlen) # 4个字节表示字典长度
sk.send(b_dic) # 具体的字典数据
with open(abs_path, 'rb') as f: # 打开文件
while filesize > 0:
content = f.read(1024) # 一次发送文件的大小
filesize -= 1024 # 文件的大小改变
sk.send(content) # 发送1024大小的文件
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
验证客户端的合法性
# # 随机生成一个字符串
# import os
# ret = os.urandom(16)
# print(ret)
#
# import hashlib
# sha = hashlib.sha1(秘钥)
# sha.update(随机字符串)
# result = sha.hexdigest()
# 第二种方法
import hashlib
import hmac # 替代hashlib模块
import os
# 秘钥+随机字符串
h = hmac.new(b'alex_sb', os.urandom(32), hashlib.sha256)
ret = h.digest()
print(ret)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
-
server
import hashlib import os import socket secret_key = b'alex_sb' sk = socket.socket() sk.bind(('127.0.0.1', 9696)) sk.listen() conn, adder = sk.accept() # 创建一个随机的字符串 rand = os.urandom(32) # 发送随机字符串 conn.send(rand) # 根据发送的字符串+ secrete key 进行摘要 sha = hashlib.sha1(secret_key) sha.update(rand) res = sha.hexdigest() # 等待接收客户端的摘要结果 res_client = conn.recv(1024).decode('utf-8') # 做对比 if res_client == res: print('是合法客户端') # 如果一致, 就显示合法客户端 # 并继续操作 conn.send(b'hello') else: conn.close() # 如果不一致立即关闭连接
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
-
client
import socket
import hashlib
secret_key = b'alex_sb'
sk = socket.socket()
sk.connect(('127.0.0.1', 9696))
# 接收客户端发送的随机字符串
rand = sk.recv(32)
# 根据发送的字符串 + secrete key 进行摘要
sha = hashlib.sha1(secret_key)
sha.update(rand)
res = sha.hexdigest()
# 根据结果发送会server端
sk.send(res.encode('utf-8'))
# 继续和server端进行通信
msg = sk.recv(1024).decode('utf-8')
print(msg)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
socketserver
- server
import time
import socketserver
class MyServer(socketserver.BaseRequestHandler):
# 必须要重写handel方法, 内部类规定的
def handle(self): # 所有的客户端都经过这个程序(每个客户端都有自己的handel)
conn = self.request # requests 是和客户端的连接
while True:
try:
content = conn.recv(1024).decode('utf-8')
conn.send(content.upper().encode('utf-8'))
time.sleep(0.5)
except ConnectionError:
break
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9696), MyServer)
server.serve_forever() # 不关闭
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9696))
while True:
sk.send('i love you'.encode('utf-8'))
msg = sk.recv(1024).decode('utf-8')
print(msg)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
多线程
进程
1.概念
# 进程的三状态图
# 就绪 运行 阻塞
# 进程的调度算法
# 给所有的进程分配资源或者分配cpu使用权的一种方法
# 短作业优先
# 先来先服务
# 多级反馈算法
# 多个任务队列,优先级从高到低
# 新来的任务总是优先级最高
# 每一个新任务几乎会立即获得一个时间片时间
# 执行完一个时间片之后会下降到下一个队列中
# 总是优先级高的任务都执行完,才执行优先级低的任务
# 并且优先级越高时间片越高
# 进程的开启和关闭
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
# multiple 多元化的
# processing 进程
# multiprocessing 多远的处理进程的模块
# from multiprocessing import Process
# import os
#
#
# def func():
# print(os.getpid(), os.getppid())
# # pid process id 进程id
# # ppid parent process id 父进程id
#
#
# if __name__ == '__main__':
# # 只会在子主进程中执行所有的代码,你写在name=main下
# print('main:', os.getpid(), os.getppid())
# p = Process(target=func)
# p.start()
# 为什么要用if __name__ == '__main__':
# a = 1
# 能不能给子进程传递参数
# from multiprocessing import Process
# import os
#
#
# def func(name, age):
# print(os.getpid(), os.getppid(), name, age)
#
#
# if __name__ == '__main__':
# # 只会在子主进程中执行所有的代码,你写在name=main下
# print('main:', os.getpid(), os.getppid())
# p = Process(target=func, args=('李锦彪', 84)) # 传参
# p.start()
# 能不能获取子进程的返回值
# 不能
# 能不能同时开启多个子进程
# 可以
# import time
# from multiprocessing import Process
# import os
#
#
# def func(name, age):
# print('%s start' % name)
# time.sleep(1)
# print(os.getpid(), os.getppid(), name, age)
#
#
# if __name__ == '__main__':
# # 只会在子主进程中执行所有的代码,你写在name=main下
# print('main:', os.getpid(), os.getppid())
# arg_lit = [('ljn', 54), ('jv', 12), ('hdhd', 11)]
# for i in arg_lit:
# p = Process(target=func, args=i) # 传参
# p.start() # 异步非阻塞
# join的用法
# import time
# from multiprocessing import Process
#
# def func(name, age):
# print('%s 的年龄: %d' % (name, age))
# time.sleep(1)
# print('发送完毕')
#
# if __name__ == '__main__':
# arg_lit = [('李锦彪', 18), ('黄欣宇', 12), ('锦欣宇', 11)]
# p_lst = []
# for i in arg_lit:
# p = Process(target=func, args=i) # 传参
# p.start() # 异步非阻塞
# p_lst.append(p)
# for p in p_lst:
# p.join() # 阻塞:直到p这个进程执行完,才继续执行代码
# print('所有的邮件发送完毕')
# 同步阻塞,异步非阻塞
# 同步阻塞:join
# 异步非阻塞:start
# 多进程之间的数据是否隔离 是
# from multiprocessing import Process
# n = 0
# def func():
# global n
# n += 1
#
# if __name__ == '__main__':
# p_1 = []
# for i in range(0, 100):
# p = Process(target=func)
# p.start()
# p_1.append(p)
# for p in p_1:
# p.join()
# print(n)
# 使用多进程实现一个并发的socket的server
#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
2.多进程实现一个并发的socket的server
server:
import socket
from multiprocessing import Process
def talk(conn):
while True:
msg = conn.recv(1024).decode('utf-8')
print(msg)
ret = msg.upper().encode('utf-8')
conn.send(ret)
conn.close()
if __name__ == '__main__':
sk = socket.socket()
sk.bind(('127.0.0.1', 9999))
sk.listen()
while True: # 来一个开一个子进程
conn, adder = sk.accept()
Process(target=talk, args=(conn, )).start()
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
client:
import socket
import time
sk = socket.socket()
sk.connect(('127.0.0.1', 9999))
while True:
sk.send(b'hello')
msg = sk.recv(1024).decode('utf-8')
print(msg)
time.sleep(0.5)
sk.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3.开启进程的另一种方法
import os
import time
from multiprocessing import Process
class MyProcess(Process):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
super().__init__()
def run(self):
time.sleep(1)
print(os.getpid(), os.getppid(), self.a, self.b, self.c)
if __name__ == '__main__':
print('-->', os.getpid())
for i in range(10):
p = MyProcess(11, 2, 3)
p.start()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
4.process类的其他方法
import os
import time
from multiprocessing import Process
class MyProcess(Process):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
super().__init__()
def run(self):
time.sleep(1)
print(os.getpid(), os.getppid(), self.a, self.b, self.c)
if __name__ == '__main__':
print('-->', os.getpid())
p = MyProcess(11, 2, 3)
p.start()
print(p.pid, p.ident)
print(p.name)
print(p.is_alive()) # 查看进程是否还活着
p.terminate() # 强制结束一个子进程 同步 异步非阻塞
print(p.is_alive())
time.sleep(0.01)
print(p.is_alive())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
5.守护进程
import time
from multiprocessing import Process
def son1():
while True:
print('-->is son1')
time.sleep(1)
def son2():
for i in range(10):
print('in son2')
time.sleep(1)
if __name__ == '__main__':
p1 = Process(target=son1)
p1.daemon = True # 表示设置p1 是一个守护进程
p1.start()
p2 = Process(target=son2)
p2.start()
time.sleep(3) # 守护进程只进行3秒,3秒后回收资源
print('in main 守护进程结束')
# p2.join() # 等待p2结束,守护进程结束
# 主进程会等待所有的子进程结束,是为了回收子进程的资源
# 守护进程会等待主进程的代码执行结束之后再结束, 而不是等待整个主进程结束
# 主进程的代码什么时候结束
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
6.锁
# 进程之间安全的问题
import time
from multiprocessing import Process, Lock
import json
def search(i):
with open('ticket', encoding='utf-8') as f:
ticket = json.load(f)
print('%s :当前的余票是%s张' % (i, ticket['count']))
def buy_ticket(i):
with open('ticket', encoding='utf-8') as f:
ticket = json.load(f)
if ticket['count'] > 0:
ticket['count'] -= 1
print('%s 买到票了' % i)
time.sleep(0.1)
with open('ticket', mode='w', encoding='utf-8') as f:
json.dump(ticket, f)
def get_lock(i, lock): # 加锁
with lock: # 代替acquire和release 并且在此基础上做一些异常处理, 保证即便一个进程的代买出错退出了,也会归还钥匙
search(i)
buy_ticket(i)
if __name__ == '__main__':
lock = Lock()
for i in range(10):
Process(target=get_lock, args=(i, lock)).start()
# import time
# from multiprocessing import Lock, Process
#
#
# def func(n, lock):
# lock.acquire() # 拿钥匙
# print('%s 被锁起来的码' % n)
# time.sleep(1)
# lock.release() # 换钥匙
#
#
# if __name__ == '__main__':
# lock = Lock()
# for i in range(10):
# Process(target=func, args=(i, lock)).start()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
7.队列
生产者消费者模型
# 进程之间的数据隔离
# 进程之间的通信(IPC)Inter Process communication
# 基于文件:同一台机器上的多个进程之间通信
# 基于socket的文件级别的通信来完成数据传递的
# 基于网络:同一台机器或者多台机器上的多进程通信
# 第三方工具(消息中间件)
# memcache
# redis
# rabbitmq
# # kafka
# from multiprocessing import Queue, Process
#
#
# def pro(q):
# for i in range(10):
# print(q.get())
#
#
# def son(q):
# for i in range(10):
# q.put('hello %s' % i)
#
#
# if __name__ == '__main__':
# q = Queue()
# p = Process(target=son, args=(q, ))
# p.start()
# p = Process(target=pro, args=(q,))
# p.start()
# 生产者消费者模型
# 爬虫的时候
# 分布式操作:celery
# 本质:就是让生产数据和消费数据的效率达到平衡并且最大话的效率
import random
import time
from multiprocessing import Process,Queue
def consumer(q, name): # 消费者:通常取得数据后还要进行某些操作
while True:
food = q.get()
if food:
print('%s 吃了 %s' % (name, q.get()))
else: break
def producer(q, name, food): # 生产者:通常在放数据之前需要先通过某些代码来获取数据
for i in range(10):
foodi = '%s%s' % (food, i)
print('%s 生产了 %s' % (name, foodi))
time.sleep(random.random())
q.put(foodi)
if __name__ == '__main__':
q = Queue()
p = Process(target=consumer, args=(q, '李锦彪'))
p1 = Process(target=producer, args=(q, '黄欣宇', '黄金'))
p2 = Process(target=producer, args=(q, '锦欣宇', '西瓜'))
p.start()
p1.start()
p2.start()
p1.join()
p2.join()
q.put(None)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
8.异步阻塞
生产者消费者模型
线程
1.threading模块
# import time
# from threading import Thread
#
#
# def func(i):
# print('start %s' % i)
# time.sleep(1)
# print('end%s' % i)
#
#
# if __name__ == '__main__':
# p_1 = []
# for i in range(10):
# t = Thread(target=func, args=(i,))
# t.start()
# p_1.append(t)
# for i in p_1:
# i.join()
# print('所有的线程都执行完了')
#
#
# # 线程不能从外部关闭terminate
# # 所有的子线程只能是自己执行完代码之后就关闭
# # current_thread() 获取当前所在线程的对象,current_thread().ident 获取线程的id
# # enumerate 列表, 储存了所有活着的线程的对象,包括主线程
# # active_count 数字,储存了所有活着的线程个数
#
# 面向对象的方式起线程
# from threading import Thread
#
#
# class MyThread(Thread):
# def __init__(self, a, b):
# self.a = a
# self.b = b
# super().__init__()
#
# def run(self):
# print(self.ident)
#
#
# t = MyThread(1, 2)
# t.start() # 开启线程中执行run()方法
# print(t.ident)
# 线程之间的数据
from threading import Thread
n = 100
def func():
global n
n -= 1
t_1 = []
for i in range(100):
t = Thread(target=func)
t.start()
t_1.append(t)
for i in t_1:
i.join()
print(n)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
2.守护线程
import time
from threading import Thread
def son():
while True:
print('in son')
time.sleep(1)
def sons():
for i in range(10):
print('in sons****')
time.sleep(1)
if __name__ == '__main__':
t = Thread(target=son)
t.daemon = True # 守护线程
t.start()
Thread(target=sons).start()
# 主线程会等待子线程结束之后才结束
# 为什么?
# 主线程结束进程就会结束
# 守护线程随着主线程的结束而结束
# 守护线程会在主线程的代码结束之后继续守护其他子线程
# 守护进程会随着主进程的代码结束而结束,如果主进程代码结束之后还有其他子进程在运行,守护进程不守护
# 守护线程 随着主线程的结束而结束,如果主线程代码结束之后还有其他子线程在运行,守护线程也守护
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
3.线程锁
import time
from threading import Thread, Lock
n = 0
def add(lock):
with lock:
for i in range(5520000):
global n
n += 1
def sub(lock):
with lock:
for i in range(5520000):
global n
n -= 1
if __name__ == '__main__':
t_1 = []
lock = Lock()
for i in range(2):
t1 = Thread(target=add, args=(lock,))
t1.start()
t2 = Thread(target=sub, args=(lock,))
t2.start()
t_1.append(t1)
t_1.append(t2)
for i in t_1:
i.join()
print(n)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
4.单例模式
import time
from threading import Thread
class A:
from threading import Lock
__instance = None
lock = Lock()
def __new__(cls, *args, **kwargs):
with cls.lock:
if not cls.__instance:
time.sleep(0.00001) # cpu 轮转
cls.__instance = super().__new__(cls)
return cls.__instance
def func():
a = A()
print(a)
if __name__ == '__main__':
for i in range(10):
Thread(target=func).start()
# 不要操作全局变量, 不要在类里操作静态变量
# queue logging 数据安全的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
5.递归锁和死锁
import time
from multiprocessing import Process, RLock, Lock
from threading import Thread
# Lock 互斥锁 效率高 多把锁容易出现死锁现象
# RLock递归(recursion)锁 效率相对低 解决死锁现象好
# l = Lock()
# l.acquire()
# print('haha') # 希望被锁住的内容
# l.release()
# r = RLock() # 在同一个线程中可以被acquire()多次
# r.acquire()
# print('希望被锁住的内容')
# r.release()
# def func(i, lock):
# lock.acquire()
# print(i, ':start')
# lock.release()
#
#
# if __name__ == '__main__':
# lock = Lock()
# for i in range(5):
# p = Thread(target=func, args=(i, lock)).start()
# ******************死锁现象****************
noodle_lock = Lock()
fork_lock = RLock()
def eat(name):
fork_lock.acquire()
print(name, '抢到面了')
print(name, '抢到叉子了')
print(name, '吃面')
time.sleep(1)
fork_lock.release()
print(name, '放下叉子了')
print(name, '放下面了')
def eat2(name):
fork_lock.acquire()
print(name, '抢到叉子了')
print(name, '抢到面了')
print(name, '吃面')
fork_lock.release()
print(name, '放下面了')
print(name, '放下叉子了')
if __name__ == '__main__':
Thread(target=eat, args=('李锦彪',)).start()
Thread(target=eat2, args=('黄欣宇',)).start()
Thread(target=eat, args=('锦欣宇',)).start()
Thread(target=eat2, args=('二蛋',)).start()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
6.队列
import queue # 线程之间的数据安全的容器队列
q = queue.Queue(4) # fifo 先进先出的队列
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
try:
q.get_nowait()
except Exception as e:
print(e)
print('队列为空继续其他内容')
print('*' * 50)
from queue import LifoQueue # last in first out 后进先出
lq = LifoQueue()
lq.put(1)
lq.put(2)
lq.put(3)
print(lq.get())
print(lq.get())
print(lq.get())
print('*' * 50)
from queue import PriorityQueue # 优先级队列
priq = PriorityQueue()
priq.put((1, 'a'))
priq.put((5, 'b'))
priq.put((6, 'x'))
priq.put((4, 'y'))
print(priq.get())
print(priq.get())
print(priq.get())
print(priq.get())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
7.池
# 什么是池
# 要在程序开始的时候,还没提交任务先创建几个线程或者进程
# 放在一个池子里,这就是池
# 为什么要用池
# 如果先开好进程/线程,那么有任务之后就可以直接使用池中的数据了
# 并且开好后的线程或者进程会一直存在池中,可以被多个任务反复利用
# 这样极大地减少了开启/关闭/调度线程/进程 的时间开销
# 池中的线程/进程个数控制了操作系统需要调度的任务个数,控制池中的单位
# 有利于提高操作系统的效率,减轻操作系统的负担
import random
import time
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
def func(name, n):
print(name, current_thread().ident, n)
time.sleep(random.randint(1, 3))
tp = ThreadPoolExecutor(20)
for i in range(20):
tp.submit(func, '李锦彪', 2)
# 向池中传数据,一次加入即可
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
协程
1.协程概述
# 协程
# 是操作系统不可见的
# 协程本质就是一条协程,多个任务在一条线程上来回切换,来规避io操作,就达到我们将一条线程中的io操作降到最低的目的
# gevent = 利用 greenlet 底层模块完成的切换 + 自动规避io的功能
# asynico = 利用 yield(让步) 底层语法完成的切换 + 自动规避io的功能
# tornado 异步的web框架
# yield from 更好的实现协程
# send 更好的实现协程
# 进程 数据隔离 数据不安全 操作系统级别 开销非常大 能利用多核
# 线程 数据共享 数据不安全 操作系统级别 开销小 不能利用多核
# 一些和文件操作相关的io只有系统能感知到
# 协程 数据共享 数据安全 用户级别 更小 不能利用多核
# 协程的所有的切换都基于用户,只有在用户级别能够感知到的io操作才会用协程模块做切换来规避(socket, 请求网页)
# 用户级别的协程还有什么好处:
# 减轻了操作系统的负担
# 一条线程下如果开了多个协程,那么给操作系统的印象是线程很忙,这样能争取一些时间片时间来被cpu执行,程序的效率就提高了
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
数据库
1.初识
# Innodb存储引擎 mysql5.6之后的默认存储引擎
# 支持事务:为了保证数据的完整性,将多个操作变成原子性操作 : 保持数据安全
# 支持行级锁:修改的行少的时候 : 修改数据频繁的操作
# 表级锁:批量修改多行时 : 对于大量数据得到同时修改
# 支持外键:约束两张表中的关联字段不能随意的添加/删除 : 能够降低数据增删改的出错率
# 写入数据
# insert into 表 values(1,2,3,4,5)
# insert into 表 (1,2,3)value(1,2,3)
# 数据类型
# float(5, 2) 保留2位小数,并四舍五入(一共多少位, 小数后多少位)
# 数据类型-时间
# 写入标准 表示
# date :20220312 YYYY-MM-DD 年月日
# time :121953 HH:MM:SS 时分秒
# datetime:20220312213512 YYYY-MM-DD HH:MM:SS 年月日时分秒
# 数据类型-字符串
# char(18) 最多只能表示255个字符
# 定长存储 存取速度快
# ‘alex’ ‘alex ’
# 身份证号、手机号码、QQ号、username、password、银行卡号
# varchar(18) 最多表示65535个字符
# 变长存储, 节省空间,存取速度慢
# ‘alex’ ‘alex4’
# 评论、朋友圈、微博
# set和enum
# enum:单选行为
# set :多选行为
# 表的完整性约束
# 无符号的:unsigned
# 不能为空:not null
# 默认 值:default xx
# 不能重复:unique
# 主键(非空+唯一):primary key (一张表只有一个)
# 联合主键:primary key(字段1,字段2.。。)
# 自增:auto_increment
# 外键:foreign_key(本表的外键键) references (其他的表)
# cascade方式:在父表上update/delete记录时,同步update/delete掉子表的匹配记录
# on update cascade
# 表与表之间的关系
# 一对多
# 电脑 软件
# 订单 商品
# 多对一
# 学生 班级
# 学院 学校
# 多对多 (第三张表 两个外键)
# 学生 班级 多对一
# 多个学生是一个班级
# 一对一
# 客户 学生
# unique foreign key
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
2.表操作
# 增 insert into 表(字段。。。) values (值。。。) 或 insert into 表 values (值。。。)
# 删
# delete from 表 where 条件;
# truncate table 表; 完全删除表
# 改 update 表 set 字段=xx, 字段=xx where 条件
# 查***********************************************
# 简单查询
# select 字段 from 表;
# 字段重命名为name:select 字段 ‘name’ from 表;
# 避免重复:select distinct 字段 from 表;
# 避免重复:select distinct 字段,字段 from 表;
# concat('a', 'v', 'b') 拼接:avb :select concat(id, ':', name) from 表;
# 默认自动拼接:avb :select concat_ws('':, id, name, on) from 表; id:name:on
# where 筛选所有符合条件的行**************************
# 比较运算符 <>!=
# 范围
# between 1 and 2000
# in
# 模糊匹配
# like
# % 通配符n个字符
# _ 通配符1个字符
# regexp
# 逻辑运算
# and not or
# 判断是否为空:
# select * from 表 where name is not null; 不为空
# select * from 表 where name is null; 为空
# 分组 ********************************************
# 根据谁分组,可以求最大小值,数量,平均值,总和,但是这个求出来的值只是和分组字段对应
# 并不和其他任何字段对应,这个时候查出来的其他字段都不生效
# group by 分组:select * from 表 group by 分组条件;
# 聚合函数:count max min sum avg
# select count(字段) from 表 group by 分组条件;
# having 过滤语句
# 在having条件中可以使用条件函数
# select 字段,count(salary) from 表 group by 分组条件 having count(salary) > 1000;
# order by 排序 默认从小到大; order by desc 从大到小排
# select * from 表 order by 字段;
# select * from 表 order by 字段,字段; 字段一相同时按字段二排
# limit m,n = limit n offset m
# 从m+1项开始,取 n 项
# 如果不写m,默认为0
# select * from 表 limit m,n;
# 多表查询****************************************
# 连表查询(快,比子查询好)
# select * from 表1,表2 where 条件; 列:(表1.字段=表2.字段)
# 表与表之间的连接方式
# 内连接:select * from 表1 inner join 表2 on 条件;
# 外连接:
# 左外连接:优先显示左边的表内容
# select * from 表1 left join 表2 on 条件;
# 右外连接:优先显示右边的表内容
# select * from 表1 right join 表2 on 条件;
# 全外连接: full join
# select * from 表1 left join 表2 on 条件 union select * from 表1 right join 表2 on 条件;
# 子查询
# select * from 表 where 条件 in (select 条件 from 表);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
3.索引
4.pymysql模块
必须的步骤
conn = pymysql.connect(host='',user='',password='',database=''); # 连接数据库
cur = conn.cursor() # 游标,为了执行mysql语句准备
ret = cur.execute('sql....') # 执行SQL语句,有返回值加参数ret
cur.execute('sql....') # 没有返回值,修改表内容
cur.commit() # 需要提交执行
print(cur.rowcount) # 获取操作影响的行数
cur.close()
conn.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
import pymysql
conn = pymysql.connect(host='127.0.0.1', user='root', password='187365', database='ljb')
# cursor=pymysql.cursors.DictCursor拿到的值放在字典中
cur = conn.cursor(cursor=pymysql.cursors.DictCursor) # cursor游标, cur 准备操作
# 通常执行异常操作
# cur.execute('select * from gds_goods;') # 执行mysql语句
# print(cur.rowcount) # 获取操作影响的行数
# try:
# cur.execute('insert into gds_goods (gds_memo, gds_name, gds_no, gds_price) '
# 'values ("大傻子","二傻子","22222","88888");')
# conn.commit() # 修改表数据,需要提交
# except:
# conn.rollback() # 回滚:第一条语句出错时,回滚执行第二条
# ret = cur.fetchone() # 拿某一个值
# print(ret)
#
# ret = cur.fetchmany(2) # 拿多个值
# print(ret)
# ret = cur.fetchall() # 拿所有的值
# for i in ret:
# print(i)
# username = input('请输入账号:')
# password = input('请输入密码:')
#
# sql = 'select * from personal_information where username=%s and password=%s;'
# cur.execute(sql, (username, password)) # sql语句 + 参数(元组或列表)
#
# print(cur.fetchone())
#
# cur.close()
# conn.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
5.事务、锁
# 锁
# 防止同时执行
# begin; 开始任务
# 执行sql语句
# commit; 提交任务
- 1
- 2
- 3
- 4
- 5
web服务
1.初识http
服务器
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 9696))
sk.listen()
while 1:
conn, adder = sk.accept()
mvg = conn.recv(1024).decode('utf-8')
print(mvg)
conn.send(b'HTTP/1.1 200 ok\r\n\r\n') # http请求信息
with open('my.html', 'rb') as f: # 读取html
data = f.read()
conn.send(data) # 发送html
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>你好!世界</h1>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
get方法
- a标签、form表单
post方法
- 一般用来提交数据
2、web框架
import socket
from threading import Thread
import time
sk = socket.socket()
sk.bind(('127.0.0.1', 9696))
sk.listen()
def html(conn):
time_target = str(time.time())
with open('my-2.html', 'r', encoding='utf-8') as f: # 读取html,以字符串形式读取,以便后续操作(动态)
data = f.read() # 读取字符串
data = data.replace('$xxoo$', time_target) # 替换
data = data.encode('utf-8')
conn.send(data) # 发送html
conn.close()
def css(conn):
with open('test.css', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def js(conn):
with open('javascript.js', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def jpg(conn):
with open('1.jpg', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def ico(conn):
with open('1.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def jqurey(conn):
with open('jquery-3.6.0.js', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
urlpatterns = [ # 反射准备
('/', html),
('/test.css', css),
('/1.jpg', jpg),
('/1.ico', ico),
('/javascript.js', js),
('/jquery-3.6.0.js', jqurey)
]
while 1:
conn, adder = sk.accept() # 等待接收信息
request_mvg = conn.recv(1024).decode('utf-8') # 接收信息
path = request_mvg.split('\r\n')[0].split(' ')[1] # 网页需要请求的路径
conn.send(b'HTTP/1.1 200 ok\r\n\r\n') # http请求信息:协议/版本 状态码 状态码原因短语
for i in urlpatterns:
if path == i[0]:
print(path)
Thread(target=i[1], args=(conn,)).start() # 线程处理并发
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
ket
from threading import Thread
import time
sk = socket.socket()
sk.bind((‘127.0.0.1’, 9696))
sk.listen()
def html(conn):
time_target = str(time.time())
with open(‘my-2.html’, ‘r’, encoding=‘utf-8’) as f: # 读取html,以字符串形式读取,以便后续操作(动态)
data = f.read() # 读取字符串
data = data.replace(‘
x
x
o
o
xxoo
xxoo’, time_target) # 替换
data = data.encode(‘utf-8’)
conn.send(data) # 发送html
conn.close()
def css(conn):
with open(‘test.css’, ‘rb’) as f:
data = f.read()
conn.send(data)
conn.close()
def js(conn):
with open(‘javascript.js’, ‘rb’) as f:
data = f.read()
conn.send(data)
conn.close()
def jpg(conn):
with open(‘1.jpg’, ‘rb’) as f:
data = f.read()
conn.send(data)
conn.close()
def ico(conn):
with open(‘1.ico’, ‘rb’) as f:
data = f.read()
conn.send(data)
conn.close()
def jqurey(conn):
with open(‘jquery-3.6.0.js’, ‘rb’) as f:
data = f.read()
conn.send(data)
conn.close()
urlpatterns = [ # 反射准备
(‘/’, html),
(‘/test.css’, css),
(‘/1.jpg’, jpg),
(‘/1.ico’, ico),
(‘/javascript.js’, js),
(‘/jquery-3.6.0.js’, jqurey)
]
while 1:
conn, adder = sk.accept() # 等待接收信息
request_mvg = conn.recv(1024).decode(‘utf-8’) # 接收信息
path = request_mvg.split('\r\n')[0].split(' ')[1] # 网页需要请求的路径
conn.send(b'HTTP/1.1 200 ok\r\n\r\n') # http请求信息:协议/版本 状态码 状态码原因短语
for i in urlpatterns:
if path == i[0]:
print(path)
Thread(target=i[1], args=(conn,)).start() # 线程处理并发
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1