概要:
上节课回顾
小知识点
python2.7多继承
IO多路复用
多线程、多进程
上节课回顾:
socekt 1、导入模块 2、创建socket 3、Python3.0 发送字节,2.0 发送字符串 send#发送一定数量,不一定全发送 发送了多少 = send("ssssssdddddfffffffff") sendall#sendall内部会调用send循环发送 sendall: while True: 10 = send("sssssdfdgsghhhjj") 10 = send("sssssdfdgsghhhjj") recv(2048) #上传文件时,最多接收2048
粘包问题 socektserver 1、自定义类 2、必须自定义handle方法 3、handle必须继承socketserver.BaseRequestHandler 4、socketserver调用上面的类 5、运行
1、socket 发送字符串 2、socket 发送文件 客户端: 文件大小 发消息 服务端: 接收消息(文件大小) 客户端: json -> 用户、密码 字符串 服务端: 用户验证(必须放在服务端) 接收,subprocess>win>gbk编码的字节 上传文件(大小) 发消息: 断点续传: seek
小知识
作用域
java/C# 不可运行(name没定义)
python/javascript 可以运行
if 1 == 1: name = 'alex' print(name) #可以输出 for i in range(10): name1 = i print(name1)
def func(): name2 = 'QL' func() print(name2) #name2只在函数里生效此处报错
#python的作用域在执行之前已经确定 name = 'alex' def f1(): print(name) def f2(): name = 'eric' f1() f2() #name = 'alex ####################### name = 'alex' def f1(): print(name) def f2(): name = 'eric' return f1 ret = f2() ret()
由新浪面试题引发的:
#问题 print(a[1]())? a = [lambda :x for x in range(10)] ########################## #首先 for循环可以写成下面的形式 #for循环10次 x >6 的 x+100 生成新的列表 li = [x+100 for x in range(10) if x >6] print(li) #然后分析此表达式 a = [lambda :x for x in range(10)] #a中的元素[函数,函数,函数] #函数在没有执行前,内部代码不执行。 #?li[0],函数 #?函数() #返回值是??? print(a[1]()) #上面的lambda表达式拆开写 li = [] for x in range(10): def fucn(): return x #fucn中没有x就到外面找 li.append(fuco) #for循环过程中已经生成li函数列表,但是函数并没执行 print(x) print(li[0]()) #当函数执行时才会用到x但此时x已经是循环之后到值9,所以li里所有元素都是9 ####升级######### li = [] for i in range(10): def fucn(x=i): #x=i执行了 return x li.append(fucn) print(li[0]())
python2.7多继承
class A: def f2(self): print('A') class B(A): def f1(self): print('B') class C(A): def f1(self): print('C') class D(B): def f1(self): print('D') class E(C): def f2(self): print('E') class F(D,E): def f1(self): print('F') obj = F() obj.f2() #它寻找f2的顺序是 F--->D--->B--->A
class A:(object) def f2(self): print('A') class B(A): def f1(self): print('B') class C(A): def f1(self): print('C') class D(B): def f1(self): print('D') class E(C): def f2(self): print('E') class F(D,E): def f1(self): print('F') obj = F() obj.f2() #执行f2方法的顺序,F--->D--->B--->E--->C---A #A是父类,继承了object类。如果当前类或父类继承了object类,那么该类是新式类,否则式经典类
python 2.7默认不继承object(经典类,一条道走到黑;继承object是新式类和3.0找的方式一样)
python 3.0默认继承object (广度优先)
IO多路复用(IO不占用内存)
概述:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
select,poll,epoll(系统底层提供的,select可以在win和Linux上执行,epoll不支持win)
select有个数监听限制1024,内部机制是for循环监听,不止监听socket,还可以监听终端等等,但不能监听文件
epoll 客户端主动告诉epoll有消息,效率高
select
监听socket对象内部是否变化了
什么时候变化?连接或收发消息
服务器端的socket对象发生变化->有新连接来了
sk:有新连接来了(sk变化)····
conn:要收“发”消息了(conn变化了)
如何读写分离?
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) #监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,rlist中就是socket对象列表,[sk] #监听conn对象,如果conn发生变化,表示有新消息发送过来了,此时rlist的值为[客户端] for r in rlist: print(r) conn,address = r.accept() #conn其实也是socket对象 conn.sendall(bytes('hello',encoding='utf-8')) rlist = [sk] ,rlist = [sk1],rlist = [sk1,sk]#发生变化 rlist = [] #不变化 rlist是空
import socket sk = socket.socket() sk.connect(('127.0.0.1',9999)) data = sk.recv(1024) print(data) while True: input(">>>:") sk.close()
#伪并发,好比10086一个客服管理着所有电话,一个电话接听后没有说话,另一个电话响了,那么他这个电话不挂,去接另一个电话,如果这个电话一直在说话,那么下个电话就得等待 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)) for r in rlist: if r == sk: conn,address = r.accept() inputs.append(conn) conn.sendall(bytes('hello',encoding='utf-8')) else: try: #客户端断开连接 服务器端移除监听 ret = r.recv(1024) if not ret: raise Exception('断开连接') except Exception as e: inputs.remove(r) 伪并发
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()
import socket import select# 监听是否变化 sk = socket.socket() sk.bind(('127.0.0.1',9999)) sk.listen(5) inputs = [sk,] outputs = [] #谁连接就添加到列表里 while True: rlist,wlist,elist= select.select(inputs,outputs,[],1) #outputs里有什么 w就获取到什么, print(len(inputs),len(rlist),len(wlist),len(outputs)) for r in rlist: if r == sk: conn,address = r.accept() 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)
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()
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,elist= select.select(inputs,outputs,[],1) #outputs里有什么 w就获取到什么, print(len(inputs),len(rlist),len(wlist),len(outputs)) for r in rlist: if r == sk: conn,address = r.accept() 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].append(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)
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()
线程
import time import threading #串行 def f1(i): time.sleep(1) print(i) #创建线程并行 t = threading.Thread(target=f1,args=(123,)) # t.setDaemon(True) #True表示主线程不等子线程 t.start() #只是准备好被cpu调度,不代表当前线程立即执行 t.join(2) #表示主线程到此,等待...直到子线程执行完毕(里面的参数2表示最多登录2秒,f1里是1秒那么这里就等1秒) print('end') #f1(1111)