网络编程2
一.大文件上传案例:
#客户端 import socket,json,os,struct client=socket.socket() client.connect(('127.0.0.1', 8080)) while True: path = input('请输入文件夹绝对路径') if not os.path.exists(path): print('文件不存在请重新输入') continue file_list = os.listdir(path) for index,file in enumerate(file_list,1): print(index,file) choice = input('请输入文件编号') if not choice.isdigit(): print('请输入数字') continue choice = int(choice) - 1 if not choice in range(len(file_list)): print('请输入范围内数字') continue file_path=os.path.join(path,file_list[choice]) file_size=os.path.getsize(file_path) d={ 'file_name':'瞅啥呢你.mp4', 'file_size':file_size, } d1=json.dumps(d).encode('utf-8') header=struct.pack('i',len(d1)) client.send(header) client.send(d1) with open(file_path,'rb')as f: for line in f: client.send(line)
#服务端 import socket,json,os,struct server=socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: conn, addr = server.accept() while True: header=conn.recv(4) dict_size=struct.unpack('i',header)[0] dict_bytes=conn.recv(dict_size) dict_data=json.loads(dict_bytes.decode('utf-8')) print(dict_data) recv_size=0 file_name=dict_data.get('file_name') file_size=dict_data.get('file_size') with open(file_name,'wb')as f: while recv_size < file_size: data=conn.recv(1024) f.write(data) recv_size += len(data) print('上传完成') break conn.close()
二.异常处理
1.什么是异常:
异常就是程序再运行的过程中出现不可预知的错误,并且再程序中并没有设计相应的处理机制那么就会以异常的形式表现出来,以致于造成程序无法运行.
2.异常的结构:
1.异常的类型:SyntaxError,ValueError,NameError等
2.异常的信息:name 'zhang' is not defined
3.异常的位置:Traceback (most recent call last):
File "D:/feiq/feiq/Recv Files/day29/代码/01 异常处理.py", line 82, in <module>
zhang
3.异常的分类:
1.语法错误:比如只写一个if,这种语法上的错误是不能容忍的,并且这种错误发生时,程序会没法运行的,再pycharm中直接飘红
#语法错误示范一 if #语法错误示范二 def test: pass #语法错误示范三 class Foo pass #语法错误示范四 print(haha
2.逻辑错误:再程序的运行中出现的错误,这种错误是一眼看不出来的,可以通过异常捕获的形式去进行捕获
#TypeError:int类型不可迭代 for i in 3: pass #ValueError num=input(">>: ") #输入hello int(num) #NameError aaa #IndexError l=['egon','aa'] l[3] #KeyError dic={'name':'egon'} dic['age'] #AttributeError class Foo:pass Foo.x #ZeroDivisionError:无法完成计算 res1=1/0 res2=1+'str'
4.常见的异常类型:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
5.异常捕获
为避免再程序运行中发生异常,我们可以对认为将发生异常的代码进行一个异常捕获,(异常捕获中的代码尽量少,且再程序中少用异常捕获,除非必要,因为大部分异常都是可以通过修改代码解决的,除类似网络编程中客户端异常退出这种不可控的可以使用异常捕获,别的不建议使用)
异常捕获的基本语句:
try: 可能出错的代码 except 出错的类型 as e: # 将报错信息赋值给变量e 出错之后的处理机制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#1 异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。 s1 = 'hello' try: int(s1) except IndexError as e: # 未捕获到异常,程序直接报错 print e #2 多分支 s1 = 'hello' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) #3 万能异常Exception s1 = 'hello' try: int(s1) except Exception as e: print(e) #4 多分支异常与万能异常 #4.1 如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么骚年,大胆的去做吧,只有一个Exception就足够了。 #4.2 如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。 #5 也可以在多分支后来一个Exception s1 = 'hello' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) except Exception as e: print(e) #6 异常的其他机构 s1 = 'hello' try: int(s1) except IndexError as e: print(e) except KeyError as e: print(e) except ValueError as e: print(e) #except Exception as e: # print(e) else: print('try内代码块没有异常则执行我') finally: print('无论异常与否,都会执行该模块,通常是进行清理工作') #7 主动触发异常 try: raise TypeError('类型错误') except Exception as e: print(e) #8 自定义异常 class EgonException(BaseException): def __init__(self,msg): self.msg=msg def __str__(self): return self.msg try: raise EgonException('类型错误') except EgonException as e: print(e) #9 断言:assert 条件 assert 1 == 1 assert 1 == 2 #10 总结try..except 1:把错误处理和真正的工作分开来 2:代码更易组织,更清晰,复杂的工作任务更容易实现; 3:毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;
三.UDP协议
UDP协议又叫数据报协议,,再UDP协议中不需要建立双向通道,通信就类似于发短信
UDP的简单应用:
#服务端 import socket server=socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1',8080)) data,addr=server.recvfrom(1024) print(data) print(addr) server.sendto(data.upper(),addr)
import socket client=socket.socket(type=socket.SOCK_DGRAM) server_addrs=('127.0.0.1',8080) client.sendto(b'shacha',server_addrs) data,addr=client.recvfrom(1024) print(data) print(addr)
2.对比TCP和UDP协议
2.1UDP协议允许客户端发送为空(TCP客户端发送为空的话,两端都会再recv处等待)
#服务端 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) print(addr)
#客户端 import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addrs = ('127.0.0.1', 8080) while True: msg = input('请输入>>>:') client.sendto(msg.encode('utf-8'), server_addrs)
2.2UDP再服务端不存在的情况下,客户端照样不会报错
UDP协议就类似于发短信,只是向那个地址发送信息,至于地址是否存在这个就不管了
2.3UDP协议支持并发
并发:看起来向同时运行的
ps:再TCP中设置有半连接池,这个会限制用户的连接数量,且只会服务一个客户端,只有那个客户端断开连接后才可以从半连接池中取出一个再进行法务,而UDP是类似发短信的形式,客户端发来请求,服务端进行处理,然后回按照这个地址将返回的信息直径返回,并再次服务另一个客户端,由于这之中的时间极短多眼看起来像同一时刻服务于多个客户端
2.4UDP协议不会粘包
#服务端 import socket server = socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) data, addr = server.recvfrom(1024) print(data) data, addr1 = server.recvfrom(1024) print(data) data, addr2 = server.recvfrom(1024) print(data)
#客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addrs = ('127.0.0.1', 8080) client.sendto(b'hello',server_addrs) client.sendto(b'hello',server_addrs) client.sendto(b'hello',server_addrs)
3.基于UDP协议写的建议QQ
# 服务端 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')) print(addr) msg=input('>>>') server.sendto(msg.encode('utf-8'), addr)
#客户端 import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addrs = ('127.0.0.1', 8080) while True: msg=input('>>>>:') msg='我是来自客户端6的%s'%msg client.sendto(msg.encode('utf-8'), server_addrs) data, addr = client.recvfrom(1024) print(data.decode('utf-8')) print(addr)
四.SocketServer
#TCP服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): # print('来啦 老弟') while True: data = self.request.recv(1024) print(self.client_address) # 客户端地址 print(data.decode('utf-8')) self.request.send(data.upper()) if __name__ == '__main__': """只要有客户端连接 会自动交给自定义类中的handle方法去处理""" server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer) # 创建一个基于TCP的对象 server.serve_forever() # 启动该服务对象
#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'))
#UDP服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): # print('来啦 老弟') while True: data,sock = self.request print(self.client_address) # 客户端地址 print(data.decode('utf-8')) sock.sendto(data.upper(),self.client_address) if __name__ == '__main__': """只要有客户端连接 会自动交给自定义类中的handle方法去处理""" server = socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyServer) # 创建一个基于TCP的对象 server.serve_forever() # 启动该服务对象
#UDP客户端 import socket import time 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.decode('utf-8'),addr) time.sleep(1)