上节回顾:
socket:
1、导入模块2、创建socket3、字节send:每次发送可能没有完全发送,send发送后会有一个返回值,是本次发送了多少。sendall:循环发送,直到全部发送完全。接收recv(2048):最多可以接收2048字节,上传文件时需要注意
粘包:socketserver:1、自定义类2、继承socketserver.BaseRequestHandler类3、重写handle方法4、socketserver 调用上面的类5、运行
本节内容:
一、作业问题:
1、socket发送字符串2、socket发送文件
客户端:
服务端:文件大小发消息
接收消息(文件大小)
断点续传
文件打开方法:
a:追加w:清空写
文件指针:seek(num)
二、小知识三、python27多继承,python35多继承四、socketserver源码
支持并发处理socketsocket源码
五、IO多路复用六、多线程、多进程
Alex甄嬛西游转
一、小知识
作用域
Python中无块级作用域Java/C# 不可以运行python/javascript 可以运行
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python中无块级作用域
if 1 == 1:
name = 'sandler'
print(name)
Python中以函数为作用域
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python中以函数为作用域
def func():
name = 'alex'
func()
print(name)
Python作用域链,由内向外找,直到找不到报错
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python作用域链,由内向外找,直到找不到报错
name = 'sandler'
def f1():
name = 'f1'
def f2():
name = 'f2'
print(name)
f1()
Python在函数为执行前,作用域已经确定,作用域链也已经确定
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python在函数为执行前,作用域已经确定,作用域链也已经确定
name = 'sandler'
def f1():
print(name)
def f2():
name = 'yuli'
f1()
f2()
二、python27多继承,python35多继承
Python2
新式类经典类==>一条道走到黑
三、SocketServer源码
支持并发处理socketSocket源码1、TCPServer =====> __init__()2、BaseServer =====> __init__()3、BaseServer =====> server_forever()4、BaseServer =====> _handle_request_noblock()5、ThreadingMixIn ===> process_request()6、ThreadingMixIn ===> process_request_thread()7、BaseServer =====> finish_process()8、BaseServer =====>9、MyClass
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# socketserver源码
import socketserver
class MyClass(socketserver.BaseRequestHandler):
def handle(self):
pass
# 创建socket对象
# accept
# server_address = ('127.0.0.1',9999)
# RequestHandlerClass = MyClass == ()
# self.RequestHandlerClass() = MyClass() == ()
# 1、obj封装了self.RequestHandlerClass = MyClass
# 2、创建了socket,bind,listen
obj = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyClass)
obj.serve_forever()
四、IO多路复用
概述:
select、poll、epoll
监听socket对象内部是否变化了?什么时候变化?连接或收发消息服务器端的socket对象发生变化==>有新链接来了....sk:有新链接来了....conn:有新消息了,要收“发”消息了IO多路复用===>监听socket对象内部是否变化了?IO多路复用测试Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',9999,))
sk.listen(5)
while True:
rlist, w, e, = select.select([sk,],[],[],1)
print(rlist)
for r in rlist:
print(r)
conn, address = r.accept()
conn.sendall(bytes('hello',encoding='utf-8'))
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9999,))
data = sk.recv(1024)
print(data)
while True:
input('>>> ')
sk.close()
IO多路复用测试(第二版)Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',9999,))
sk.listen(5)
inputs = [sk,]
while True:
rlist, w, e, = select.select(inputs,[],[],1)
print(len(inputs),len(rlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?conn其实是socket对象
inputs.append(conn)
conn.sendall(bytes('hello',encoding='utf-8'))
else:
r.recv(1024)
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input('>>> ')
sk.sendall(bytes(inp,encoding='utf-8'))
sk.close()
IO多路复用测试之读写分离Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试服务端
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',9999,))
sk.listen(5)
inputs = [sk,]
outputs = []
while True:
rlist, wlist, e, = select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(outputs),len(wlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?conn其实是socket对象
inputs.append(conn)
conn.sendall(bytes('hello',encoding='utf-8'))
else:
print('========')
try:
ret = r.recv(1024)
if not ret:
raise Exception('断开连接')
else:
outputs.append(r)
except Exception as e:
inputs.remove(r)
for w in wlist:
w.sendall(bytes('response',encoding='utf-8'))
outputs.remove(w)
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试客户端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input('>>> ')
sk.sendall(bytes(inp,encoding='utf-8'))
print(sk.recv(1024))
sk.close()
IO多路复用测试之读写分离(升级版)Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试服务端
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',9999,))
sk.listen(5)
inputs = [sk,]
outputs = []
messages = {}
while True:
rlist, wlist, e, = select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(outputs),len(wlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?conn其实是socket对象
inputs.append(conn)
messages[conn] = []
conn.sendall(bytes('hello',encoding='utf-8'))
else:
print('========')
try:
ret = r.recv(1024)
if not ret:
raise Exception('断开连接')
else:
outputs.append(r)
messages[r].appent(ret)
except Exception as e:
inputs.remove(r)
del messages[r]
for w in wlist:
msg = messages[w].pop()
resp = msg + bytes('response',encoding='utf-8')
w.sendall(resp)
outputs.remove(w)
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试客户端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input('>>> ')
sk.sendall(bytes(inp,encoding='utf-8'))
print(sk.recv(1024))
sk.close()
五、多线程、多进程
1、一个应用程序,可以有多进程和多线程2、默认:单进程,单线程3、单进程,多线程
IO操作,不占用CPU
多线程提高并发
计算型操作,占用CPU
多进程提供并发
4、GIL,全局解释器锁==================================>>多线程、多进程 提供并发IO密集型:使用多线程计算密集型:使用多进程多线程示例:
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 多线程并发
import threading
import time
def f1(args):
time.sleep(1)
print(args)
t = threading.Thread(target=f1, args=(123,))
t.start()
f1(111)
多线程示例2:
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 多线程并发
import threading
import time
def f1(args):
time.sleep(5)
print(args)
# 单进程,单线程的应用程序
for i in range(10):
f1(i)
# 单进程,多线程的应用程序
for i in range(10):
t = threading.Thread(target=f1, args=(i,))
t.setDaemon(True) # true,表示主线程不等此子线程结束,
t.start() # 不代表当前线程会被立即执行
t.join() # 表示主线程到此,等待子线程执行结束,才会继续往下执行,参数表示主线程在此最多等待几秒