异常处理 udp通信

上传电影

1.循环打印某个文件夹的所有文件

2.用户选取要上传的文件

3.将用户选择的文件上传到服务器

4.服务器保存你文件

客户端
import socket
import os
import json
import struct
client = socket.socket()
client.connect(('127.0.0.1',8080))
while True:
    MOVIE_DIR = 'G:\Python10期脱产视频\day01\视频'
    movie_list = os.listdir(MOVIE_DIR)
    for i, movie in enumerate(movie_list,1):  # 获取电影列表,循环展示
        print(i,movie)
    choice = input('>>>:').strip()  #用户选择
    if choice.isdigit():   # 判断是否是数字
        choice = int(choice) - 1
        if choice in range(len(movie_list)):   # 判断用户选择的是否在列表中
            path = movie_list[choice]   # 获取用户上传的文件路径
            print(path)
            file_path = os.path.join(MOVIE_DIR,path)   #获取文件路径
            file_size = os.path.getsize(file_path)  #获取文件大小
            print(file_path)
            print(file_size)
            res = {'name':'大保健','file_size':file_size}  #定义一个字典
            json_d = json.dumps(res)   # 序列化字典
            json_bytes = json_d.encode('utf-8')
            print(json_bytes)
            header = struct.pack('i',len(json_bytes))  #制作一个报头
            client.send(header)  #发送报头
            client.send(json_bytes)  # 发送字典
            with open(file_path,'rb')as f:   # 发文件数据
                for line in f:
                    client.send(line)
        else:
            print('not in range')
    else:
        print('must be a number')

服务端
import socket
import struct
import json
import os
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
    sock,addr = server.accept()
    while True:
        try:
            header_len = sock.recv(4)   # 解析字典报头
            header_len = struct.unpack('i',header_len)[0]
            header_dic = sock.recv(header_len)  # 接收字典数据
            real_dic = json.loads(header_dic.decode('utf-8'))
            print(real_dic)
            print(real_dic.get('file_size'))
            total_size = real_dic.get('file_size')  # 获取字典长度
            print(total_size)
            recv_size = 0  #循环写入文件
            print(real_dic.get('file_size'))
            with open(real_dic.get('name'),'wb')as f:
                while recv_size < total_size:
                    data = sock.recv(1024)
                    f.write(data)
                    recv_size += len(data)
                print('上传成功')
        except ConnectionResetError as e:
            print(e)
            break
    sock.close()

 

异常处理

异常处理是在程序运行中出现不可预知的错误,并且该机制没有对应的处理机制,就会报错,使的整个程序无法正常运行

异常的结构

1.异常的位置: Traceback (most recent call last):
                    File "D:/python脱产10期视频/day29/01 异常处理.py", line 1, in <module>fdsdfsdf

2.异常的类型: NameError

3.异常的信息: name 'fdsdfsdf' is not defined

 

异常分两类:

1. 语法错误:能够一眼看得到,能够立马解决

2.逻辑错误:一眼看不出来.可以采用异常处理进行捕获

常见的错误类型
            NameRrror     名字错误
            SyntaxError  语法错误
            KeyError     键不存在
            ValueError   值错误
            IndexError   索引错误

 

如何避免异常处理: 在可能出现bug的代码上方try一下, try越少越好

try:

  可能出错的代码

except 出错的类型    as  e:  #  将报错的信息赋值给变量

  出错之后的处理机制

try:
    res = {'name':''}
    print(res['pwd'])
    print(res.get('pwd','None'))
except KeyError:   #  键值错误
    print('KeyError')
except NameError:   # 变量名错误
    print('NameError')
except IndexError:    # 索引错误
    print('IndexError')
except Exception:     # 所有异常都可以捕获
    print('Exception')
except BaseException:   # 所有异常都可以捕获
    print('BaseException')
try:
    l = [1,2,3]
    l[111]
except Exception:  # 万能异常  所有的异常类型都被捕获
    print('老子天下无敌')
else:
    print('被检测的代码没有任何的异常发生 才会走else')
finally:
    print('无论被检测的代码有没有异常发生 都会在代码运行完毕之后执行我')

#主动抛异常
if 'egon' == 'DSB':
    pass
else:
    raise TypeError('尽说大实话')
# 关键字raise就是主动抛出异常

l = [1,2,3]
assert len(l) < 0  # 断言  预言
# 猜某个数据的状态 猜对了 不影响代码执行 正常走
# 猜错了  直接报错

# 自定义异常
class MyError(BaseException):
    def __init__(self, msg):
        super().__init__()
        self.msg = msg
    def __str__(self):
        return '<dfsdf%ssdfsdaf>' % self.msg

raise MyError('我自己定义的异常')  # 主动抛出异常其实就是将异常类的对象打印出来,会走__str__方法

UDP通信

   数据报协议(自带报头)

   没有双向通道,通信类似于发短信

udp 使用

服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)  #UDP协议
server.bind(('127.0.0.1',8080))
while True:
    data,addr = server.recvfrom(1024)
    print('数据:',data)
    print('地址:',addr)
    server.sendto(data.upper(),addr)

服务端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)
while True:
    client.sendto(b'hello',server_address)
    data,addr = client.recvfrom(1024)
    print('服务端发来的数据',data)
    print('服务端发来的地址',addr)

 

1. udp协议客户端允许发空

2. udp协议不会粘包

3. udp协议服务端不存在的情况下,客户照样不会报错

4. udp协议支持并发

简易版qq

客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)
while True:
    res = input('>>>:').strip()
    client.sendto(res.encode('utf-8'),server_address)
    data,server_address = client.recvfrom(1024)
    print(data.decode('utf-8'))

服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
    data,addr = server.recvfrom(1024)
    print(data.decode('utf-8'))
    res = input('>>>:').strip()
    server.sendto(res.encode('utf-8'),addr)

 

udp类似于发短信

tcp类似于打电话

tcp 解决粘包
客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1',8080))
while True:
    client.send(b'hello')
    data = client.recv(1024)
    print(data.decode('utf-8'))

服务端
import socketserver
class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(1024)
            print(self.client_address)  # 客户端地址
            print(data.decode('utf-8'))  #
            self.request.send(data.upper())
if __name__ == '__main__':    # 只要有客户连接,会自定义交给类中handler方法去处理
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer)
    server.serve_forever()   #启动该服务器

 

并发: 看起来像同时运行的

并行: 真正的运行

网络编程    TCP粘包问题,上传下载文件

 

posted @ 2019-08-08 21:30  大爷灰  阅读(802)  评论(0编辑  收藏  举报