异常处理
try:
names[3]
data["name"]
except KeyError as e:#抓取一个错误
print("没有这个key", e)
except (err1, err2) as e:#抓取两个错误
print("列表操作错误", e)
except Exception as e:#抓取所有错误
print("出错了", e)
else:
print("一切正常")
finally:
print("无论对错都执行")
断言
assert type(obj.name) is str
print("断言正确")
Socket网络编程
-
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
- 一些其他协议
协议 功能用处 端口号 Python 模块 http 网页访问 80 httplib, urllib, xmlrpclib smtp 发送邮件 25 smtplib dns 域名/IP地址转换 53 ftp 文件传输 20 ftplib, urllib ssh 为网络服务提供安全性的协议 22 snmp 简单网络管理协议 icmp ping 互联网控制报文协议 dhcp 动态主机配置协议 ...
- 一些其他协议
-
所有协议本质上都是由:发send和收receive
-
Socket是对以上协议发send和收receive接口的封装
-
粘包:服务端连续发送数据是,缓存区里两条挨着的数据会黏在一起发送给客户端
-
解决办法:两次数据发送中间加一次交互
-
OSI七层
应用 表示 会话 传输 TCP/IP 三次握手,四次断开 1、syn->2、syn/ack->3、ACK UDP不安全的数据传输 网络 ip 数据链路 mac 物理层
-
一个机器(服务器)上可以开65535个端口(port) 通信的实现要通过IP+port
Nginx 80 MySQL 3306
-
发送端流程
import socket socket.TCP/IP connect(a.ip,a.port) socket.send(hello) socket.recv() socket.close()
- 实例 ```python import socket client = socket.socket() # 声明socket类型,同时生成socket连接对象 client.connect(("localhost", 9000)) # client.send(b"Hello World!")#python3里要转字节传输 while True: msg = input(">>:").strip() if len(msg) == 0: continue client.send(msg.encode("utf-8")) data = client.recv(1024) # 收1024字节 print("recv:", data.decode()) client.close() ```
-
接收端(服务端)
import socket socket.TCP/IP listen(ip,port) waiting()等 recv()收 send()回复
- 实例
server = socket.socket() # 声明socket类型,同时生成socket连接对象 server.bind(("localhost", 9000)) # 绑定到要监听端口 server.listen(5) # 监听 print("我要开始等电话了") while True: conn, addr = server.accept() # 等电话打进来 # conn就是客户端连过来而在服务器端为其生成的一个连接实例 print(conn, addr) print("电话来了") while True: data = conn.recv(1024) print("recv:", data.decode()) if not data: print("client has lost...") conn.send(data.upper())#服务端最多能发送32M server.close()
- 实例
-
Socket Families(地址簇)
socket.AF_UNIX unix本机进程间通信 socket.AF_INET ipV4 socket.AF_INET6 ipV6 Socket Types socket.SOCK_STREAM #for tcp socket.SOCK_DGRAM #for udp socket.SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、IGMP的网络报文,而SOCK_RAW可以;其次SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头(可以伪造物理攻击即doc攻击)。
ftp server流程
1、读取文件
2、检测文件是否存在
3、打开文件
4、检测文件大小
5、发文件大小给客户端
6、等客户端确认
7、开始边读边发数据
8、发送md5
多任务 - 线程
-
概念:简单地说就是操作系统可以同事运行多个任务,如同时听歌、用word工作、浏览器上网
-
单核CPU执行多任务:操作系统让任务交替执行,任务1执行0.01s,任务2执行0.01s,任务,3执行0.01s...
- 并行:真的多任务
- 并发:假的多任务(时间片轮转)
-
线程:
-
一个程序运行起来之后,一定有一个执行代码的东西,这个东西就叫做线程
-
python的thread模块是比较底层的模块,python的threading模块对thread做了一些包装,可以更加方便的被使用
-
查看正在运行的线程用:threading.enumerate()
-
当调用Thread的时候,不会创建线程
-
当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及让个这个线程开始运行
-
同时创建多个子线程,子线程执行的先后顺序是不固定的(随机的)
-
如果创建Thread时执行的函数,函数运行结束就意味着这个子线程结束
-
子线程一定先于主线程结束
-
创建子线程:
- 通过指定函数创建子线程
- 创建带参数的线程threading.Thread(target=test1, args=(参数,))
- target:指定将来这个线程去哪个函数执行代码
- args:指定将来调用函数的时候传递什么数据过去(args必须是个元组)
- 通过继承Thread类创建子线程
- 通过指定函数创建子线程
-
多线程共享全局变量:
- 在一个函数中对全局变量进行修改的时候,是否需要用global进行说明,要看是否对全局变量的指向进行了修改
- 如果修改了指向,那么必须用global,如果仅仅是修改了指向的空间中的数据,此时不必使用global
- 多线程共享全局变量的时候会存在资源竞争
-
同步
- 同步就是协同步调,按预定的先后顺序运行,如:你说完·我再说
- 进程、线程同步,可以理解为进程或线程A和B一块配合,A执行到一定程度的时候要依靠B的某个结果, 于是停下来,让B运行;B执行,将结果给A;A再继续操作
-
互斥锁
- 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
-
死锁
-
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源,并且同时等待对方的资源,就会造成死锁
-
避免死锁
- 程序设计时要尽量避免(银行家算法)
- 添加超时时间
-
-
进程、线程、协程对比
- 进程是资源分配单位
- 线程是操作系统调度的单位
- 进程切换需要的资源最大,效率很低
- 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
- 协程切换任务资源很小,效率高
- 多进程、多线程根据CPU核数不一样可能是并行的,但是协程是在一个线程中所以是并发
SocketServer:实现并发处理
SocketServer.TCPServer
SocketServer.UDPServer
SocketServer.UnixStreamServer
SocketServer.UnixDatagramServer
- 1、你必须自己创建一个请求处理类,并且这个类要继承BaseRequestHandler,并且还有重写父亲类里的handler()
- 2、你必须实例化TCPServer,并且传递server ip 和你上面创建的请求处理类,给这个TCPServer
- 3、调用handle_request()和server_forever()方法
- server.handle_request()#只处理一个请求
- server.server_forever()#处理多个请求,永远执行
- 4、调用server_close()去关闭这个socket
- 实例
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): ''' 继承socketserver,重写handle方法 ''' def handle(self): while True: try: # self.request是TCP socket 链接到客户端 self.data = self.request.recv(1024).strip() print("{} worte:".format(self.client_address[0])) print(self.data) self.request.sendall(self.data.upper()) except ConnectionResetError as e: print("err:",e) break if __name__ == "__main__": HOST, PORT = "localhost", 9000 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)#多线程 # server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)#多进程(linex) server.serve_forever()
- 实例
练习:开发一个支持多用户在线的FTP程序
要求:
1、用户加密认证
2、允许同时多用户登录
3、每个用户有自己的home目录,且只能访问自己的home目录
4、对用户进行磁盘配额,每个用户的可用空间不同
5、允许用户在ftp server上随意切换目录
6、允许用户查看当前目录下的文件
7、允许上传和下载文件,保证文件的一致性
8、文件传输过程中显示进度条
9、附加功能:支持文件断点续传