1.基于TCP协议传输大文件
可以根据TCP粘包问题的处理方法实现大文件的传输
上传大文件
1 import socket 2 import os 3 import struct 4 import json 5 6 client = socket.socket() 7 client.connect(('127.0.0.1',8080)) 8 9 while True: 10 MOVIE_DIR = r'F:\迅雷下载' 11 movie_list = os.listdir(MOVIE_DIR) 12 for i,movie in enumerate(movie_list,1): 13 print(i,movie) 14 choice = input('>>>:').strip() 15 if not choice.isdigit(): 16 print('请输入数字') 17 continue 18 choice = int(choice)-1 19 if choice not in range(0,len(movie_list)): 20 print('请输入正确的编号') 21 continue 22 movie_name = movie_list[choice] 23 movie_path = os.path.join(MOVIE_DIR,movie_name) 24 size = os.path.getsize(movie_path) 25 # 生成一个字典 26 d = {'name':movie_name,'size':size,'path':movie_path} 27 json_d = json.dumps(d) 28 # 生成一个字典报头 29 header = struct.pack('i',len(json_d)) 30 # 发送字典报头 31 client.send(header) 32 # 发送字典 33 client.send(json_d.encode('utf-8')) 34 # 发送真实数据 35 with open(movie_path,'rb')as f: 36 for line in f: 37 client.send(line) 38 print('上传成功')
1 import socket 2 import struct 3 import json 4 import os 5 6 server = socket.socket() 7 server.bind(('127.0.0.1',8080)) 8 server.listen(5) 9 10 while True: 11 conn, addr = server.accept() 12 while True: 13 try: 14 # 接收报头 15 header = conn.recv(4) 16 dict_len = struct.unpack('i',header)[0] 17 # 接收字典 18 d = conn.recv(dict_len).decode('utf-8') 19 dict = json.loads(d) 20 # 字典中取出数据 21 movie_name = dict.get('name') 22 movie_size = dict.get('size') 23 save_path = os.path.join(movie_name) 24 recv_size = 0 25 # 接收真实数据 26 with open(save_path,'wb')as f: 27 while recv_size < movie_size: 28 data = conn.recv(1024000000) 29 f.write(data) 30 recv_size += len(data) 31 c = recv_size / movie_size 32 d = "%.2f%%" % (c * 100) 33 print(d) 34 print('接收上传完毕') 35 except ConnectionResetError as e: 36 print(e) 37 break 38 conn.close()
下载大文件
1 import socket 2 import json 3 import struct 4 5 client = socket.socket() 6 client.connect(('127.0.0.1',8080)) 7 8 while True: 9 # 接收列表的报头 10 list_header = client.recv(4) 11 # 解包获取列表的长度 12 list_len = struct.unpack('i',list_header)[0] 13 # 接收列表 14 movie_json = client.recv(list_len).decode('utf-8') 15 movie_list = json.loads(movie_json) 16 for i,movie in enumerate(movie_list,1): 17 print(i,movie) 18 choice = input('>>>:').strip() 19 if not choice.isdigit(): 20 print('请输入数字') 21 continue 22 choice = int(choice) - 1 23 if choice not in range(0,len(movie_list)): 24 print('请输入正确的编号') 25 continue 26 # 发送选择 27 client.send(str(choice).encode('utf-8')) 28 # 接收报头 29 dict_header = client.recv(4) 30 # 解包获取字典长度 31 dict_len = struct.unpack('i',dict_header)[0] 32 # 接收字典 33 d = client.recv(dict_len).decode('utf-8') 34 movie_dict = json.loads(d) 35 # 获取字典中的信息 36 movie_name = movie_dict.get('name') 37 movie_size = movie_dict.get('size') 38 recv_size = 0 39 # 接收真实数据 40 with open(movie_name,'wb')as f: 41 while recv_size < movie_size: 42 data = client.recv(1024) 43 f.write(data) 44 recv_size += len(data) 45 c = recv_size/movie_size 46 d = "%.2f%%" % (c * 100) 47 print(d) 48 print('下载成功')
1 import json 2 import socket 3 import os 4 import struct 5 6 7 server = socket.socket() 8 server.bind(('127.0.0.1',8080)) 9 server.listen() 10 11 while True: 12 conn, addr = server.accept() 13 while True: 14 try: 15 MOVIE_DIR = r'F:\迅雷下载' 16 # 生成电影列表 17 movie_list = os.listdir(MOVIE_DIR) 18 movie_json = json.dumps(movie_list) 19 list_header = struct.pack('i',len(movie_json)) 20 # 发送列表的报头 21 conn.send(list_header) 22 # 发送列表 23 conn.send(movie_json.encode('utf-8')) 24 # 接收选择 25 choice = conn.recv(1024).decode('utf-8') 26 choice = int(choice) 27 movie_name = movie_list[choice] 28 # 获取电影的信息,生成字典 29 movie_path = os.path.join(MOVIE_DIR,movie_name) 30 size = os.path.getsize(movie_path) 31 d = {'name':movie_name,'size':size} 32 # 制作电影的报头 33 dict = json.dumps(d) 34 dict_header = struct.pack('i',len(dict)) 35 # 发送报头 36 conn.send(dict_header) 37 # 发送字典 38 conn.send(dict.encode('utf-8')) 39 # 发送真实数据 40 with open(movie_path,'rb')as f: 41 for line in f: 42 conn.send(line) 43 print('发送完成') 44 except ConnectionResetError as e: 45 print(e) 46 break 47 conn.close()
2.异常处理
什么是异常
异常就是程序在运行过程中出现了不可预知的错误
并且该错误没有对应的处理机制,会以异常的形式表现出来
造成的影响就是整个程序无法再正常运行
异常的结构
1.异常的类型:NAMEERROR
2.异常的信息:name 'fdsdfsdf' is not defined
3.异常的位置:Traceback (most recent call last):后面跟的就是出现异常的位置,点击就能自动找到该位置
异常的种类,分为两大类
1.语法错误:
这种是运行程序立刻就能发现的,发现之后可以立刻解决
2.逻辑错误
这种错误一眼并不能看出来,针对这种错误,我们可以使用异常处理机制来捕获
常见的错误类型:
NAMERROR 名字错误
SyntaxError 语法错误
KeyError 键不存在
ValueError 值错误
IndexError 索引错误\
如何避免
异常处理:
在会出现异常代码块上方try一下.注意:try内部的代码块越少越好
语法:
1 try: 2 # 可能出现错误的代码块 3 except 错误的类型 as e: # 将错误的信息赋值给变量e 4 # 出错之后的代码块
万能异常处理Exception和BaseException
1 # 两个万能异常处理Exception和BaseException 2 try: 3 l = [1,2,3] 4 l[123] 5 except Exception as e: 6 print(e) 7 print('被我处理掉了') 8 9 try: 10 d = {'name':'sxc'} 11 d['pwd'] 12 except BaseException as e: 13 print(e) 14 print('被我处理掉了')
异常处理的else和finally
1 # else和finally 2 try: 3 d = {'name':'sxc'} 4 d['name'] 5 except BaseException as e: 6 print(e) 7 print('被我处理掉了') 8 else: 9 print('没有出错就会走else') 10 finally: 11 print('不管有没有出错都会走finally')
主动抛出异常
1 # 主动抛出异常 2 if 1 > 2: # 异常判断条件 3 pass 4 else: 5 raise TypeError('不存在的') # raise + TypeError + 异常信息
断言
1 # 断言,预言 2 l = [1,2,3] 3 assert l[0] < 0
自定义异常
1 # 自定义异常 2 class MyError(BaseException): 3 def __init__(self,msg): 4 super().__init__() 5 self.msg = msg 6 def __str__(self): 7 return '<%s>' %self.msg 8 9 raise MyError('自定义的异常')
3.基于UDP通信的socket
又称数据包协议,UDP协议是无连接的,启动之后可以直接接收消息,不需要提前建立连接,类似于发短信
UDP通信socket的简单使用
1 import socket 2 import time 3 4 client = socket.socket(type=socket.SOCK_DGRAM) 5 server_addr = ('127.0.0.1',8080) 6 7 while True: 8 client.sendto(b'hello',server_addr) 9 data,addr = client.recvfrom(1024) 10 print(data) 11 print(addr)
1 import socket 2 3 server = socket.socket(type=socket.SOCK_DGRAM) 4 server.bind(('127.0.0.1',8080)) 5 # 面向连接的不需要半连接池,也不需要建立双向通道 6 while True: 7 data, addr = server.recvfrom(1024) 8 print(data) 9 print(addr) 10 server.sendto(data.upper(),addr)
UDP通信和TCP通信的区别
1.UDP协议允许发空
2.UDP协议不会粘包
3.UDP协议服务端不存在的情况下.客户端不会报错
4.UDP协议支持并发
基于UDP实现一个简易版本的QQ
1 import socket 2 3 server = socket.socket(type=socket.SOCK_DGRAM) 4 server.bind(('127.0.0.1',8080)) 5 6 while True: 7 data ,addr = server.recvfrom(1024) 8 print(data.decode('utf-8')) 9 msg = input('>>>:') 10 server.sendto(msg.encode('utf-8'),addr)
1 import socket 2 3 client = socket.socket(type=socket.SOCK_DGRAM) 4 server_addr = ('127.0.0.1',8080) 5 6 while True: 7 msg = input('>>>:') 8 msg1 = '来自客户端1的消息%s'%msg 9 client.sendto(msg1.encode('utf-8'),server_addr) 10 data,addr = client.recvfrom(1024) 11 print(data.decode('utf-8'))
如需要多个客户通信,只要多开几个客户端就行了
4.SocketServer模块
可以实现TCP/UDP并发通信
TCP并发通信
1 import socket 2 3 client = socket.socket() 4 client.connect(('127.0.0.1',8080)) 5 6 while True: 7 client.send(b'hello') 8 data = client.recv(1024) 9 print(data.decode('utf-8'))
1 import socketserver 2 3 class MyServer(socketserver.BaseRequestHandler): 4 def handle(self): 5 while True: 6 data = self.request.recv(1024) 7 print(self.client_address) # 客户端地址 8 print(data.decode('utf-8')) 9 self.request.send(data.upper()) 10 11 12 if __name__ == '__main__': 13 # 当有客户端来连接会自动交给自定义类中的handle方法处理 14 server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer) # 创建一个基于TCP的对象 15 server.serve_forever() # 启动这个对象
UDP并发通信
1 import socket 2 import time 3 4 client = socket.socket(type=socket.SOCK_DGRAM) 5 server_addr = ('127.0.0.1',8080) 6 7 while True: 8 client.sendto(b'hello',server_addr) 9 data,addr = client.recvfrom(1024) 10 print(data.decode('utf-8'),addr) 11 time.sleep(1)
1 import socketserver 2 3 class MyServer(socketserver.BaseRequestHandler): 4 def handle(self): 5 while True: 6 data,sock = self.request 7 print(self.client_address) # 客户端地址 8 print(data.decode('utf-8')) 9 sock.sendto(data.upper(),self.client_address) 10 11 12 if __name__ == '__main__': 13 # 当有客户端来连接会自动交给自定义类中的handle方法处理 14 server = socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyServer) # 创建一个基于UDP的对象 15 server.serve_forever() # 启动这个对象