程序在运行过程中出现了不可预知的错误
并且该错误没有对应的处理机制,那么就会以异常的形式表现出来
造成的影响就是整个程序无法运行
1.异常的类型
2.异常的信息
3.异常的位置
分为两大类 1.语法错误 是你程序立刻就能解决的,这种错误是不能被容忍的 语法上的错误 发现之后应该立刻解决 2.逻辑错误 这种错是可以被容忍的 因为一眼看不出来 针对逻辑上的错误 可以采用异常处理机制进行捕获
except 可以叠加写
错误发生之后 会立刻停止代码的运行
执行 except语句 比对错误类型
except NameError: print('捕获了NameError') except KeyError: print('捕获了KeyError')比如首先出现了NameError 就不会继续查看是否有KeyError
所有的错误类型都能捕获
except Exception
except BaseException
这两个都是万能异常处理的方法
Exception 继承了BaseException
except 之后还可以加一个else :
最后也可以加一个finally
(try.. except.. else.. finally..)
except Exception: print('万能异常捕获') else: print('没报错,才会走else') finally: print('无论如何,这句都会打印')# finally的用处:比如在代码结束之后结束读写啥的
# 关键字raise就是主动抛出异常
# 断言不成立直接报错
l = [1,2,3] assert len(l) < 0 # assert 断言,预言,猜某个数据的状态,猜对了不影响代码执行,猜错了直接报错报错类型,其实对应的就是一个个类(可以自定义拼接异常的格式)
class MyError(BaseException): def __init__(self, msg): super().__init__() self.msg = msg def __str__(self): return f'----<{self.msg}>----' raise MyError('自定义的异常') # Traceback (most recent call last): # File "E:/PyCharm 2019.1.3/ProjectFile/day010/day029/test.py", line 15, in <module> # raise MyError('自定义的异常') # __main__.MyError: ----<自定义的异常>----UDP协议又叫用户数据报协议
它没有双向通道,类似于发短信(只管发,不管对方有没有收到,不需要对方立即回应)
UDP的程序可以先启动客户端再启动服务端(客户端发数据给服务端之前都没问题)
UDP类似于发短信
TCP类似于打电话,你一句我一句的
服务端
import socket server = socket.socket(type=socket.SOCK_DGRAM) # type=socket.SOCK_DGRAM 指定成 UDP 协议 type=socket.SOCK_STREAM TCP协议(默认就是,不用指定) server.bind(('127.0.0.1', 8080)) # UDP 不需要设置半连接池(server.listen(5)),也没有半连接池的概念 # UDP 没有双向通道,所以也不需要建立连接(conn, addr = server.accept()) # 直接就是通信循环 while True: # 这里只需要直接通信(交互)即可 data, addr = server.recvfrom(1024) print("数据:", data.decode('utf-8')) # 客户端发来的消息 print("地址:", addr) # 客户端的地址 re_msg = input("Please input your response msg:").strip() # 会阻塞在这里,这里过了,才能发出信息,看到下一条信息 server.sendto(re_msg.encode('utf-8'), addr) # 向客户端发送消息 # 数据: hi # 地址: ('127.0.0.1', 64821) # Please input your response msg:o hi # 数据: hihihi # 地址: ('127.0.0.1', 64823) # Please input your response msg:xxixixi # 数据: aha e # 地址: ('127.0.0.1', 64828) # Please input your response msg:emmm? # 数据: # 地址: ('127.0.0.1', 64828) # Please input your response msg:adsa客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM) # UDP 不需要建立连接(client.connect(('127.0.0.1', 8080))) server_addr = ('127.0.0.1', 8080) # UDP sendto发消息时需要一个服务器的地址及端口号 while True: msg = input("Please input your msg:").strip() client.sendto(msg.encode('utf-8'), server_addr) # 向服务器发送数据,要附带服务器端地址及端口(基于网络传输的数据都必须是二进制的) data, msg_from_server_addr = client.recvfrom(1024) # 收到消息,且得到地址 print("服务端发来的数据:", data.decode('utf-8')) print("服务器端的ip及端口", msg_from_server_addr) # 窗口1 # Please input your msg:hi # 服务端发来的数据: o hi # 服务器端的ip及端口 ('127.0.0.1', 8080) # Please input your msg: # 窗口2 # Please input your msg:hihihi # 服务端发来的数据: xxixixi # 服务器端的ip及端口 ('127.0.0.1', 8080) # Please input your msg: # 窗口3 # Please input your msg:aha e # # 服务端发来的数据: emmm? # 服务器端的ip及端口 ('127.0.0.1', 8080) # Please input your msg:服务端发来的数据: adsa # 服务器端的ip及端口 ('127.0.0.1', 8080) # Please input your msg:1.UDP 允许发空数据,不会有影响
2.UDP 直接启动客户端未启动服务端不会报错
3.UDP 不会有粘包问题(自带报头)
4.UDP 支持并发
服务端
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) data, addr1 = server.recvfrom(1024) print(data) data, addr2 = server.recvfrom(1024) print(data)客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM) while True: msg = input(">>>:") # ------------------------------------------- # 1.UDP 允许发空数据,不会有影响 # ------------------------------------------- # UDP自带报头,就算数据为空,另一端也能处理 client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) # 第二参数,目标服务器地址 # ------------------------------------------- # 2.UDP 直接启动客户端未启动服务端不会报错 # 发数据找不到服务端也还是会报错 # ------------------------------------------- # 下面两行代码直接注释掉,服务端没启动,都不会报错,只管给服务器发(收没收到不管) # data, server_addr = client.recvfrom(1024) # print(data) # ------------------------------------------- # 3.UDP 不会有粘包问题(自带报头) # ------------------------------------------- # client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) # client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) # client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) # # server.sendto(data.upper(), addr) # server.sendto(data.upper(), addr) # server.sendto(data.upper(), addr) # ------------------------------------------- # 4.UDP 支持并发 # TCP是保持连接,而UDP不需要保持连接 # 与一个客户端断开连接才会和下一个客户端建立连接 # -------------------------------------------服务器端
import socket server = socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) while True: data, client_addr = server.recvfrom(1024) print(data.decode('utf-8')) msg = input(">>>:").strip() server.sendto(msg.encode('utf-8'), client_addr) # 来自star3的消息:helo # >>>:hi # 来自star2的消息:aha # >>>:haa # 来自star的消息:hello world # >>>:ha # 来自star2的消息:jason nnn # >>>:jj客户端1,2,3共用同一份代码
import socket client = socket.socket(type=socket.SOCK_DGRAM) username = 'star' server_address = ('127.0.0.1', 8080) # 指定一个发消息的目标服务器 while True: msg = input(">>>:").strip() msg = f'来自{username}的消息:{msg}' # 是哪个用户名发出的数据不应该由这里传过去,用户可以随便改,实际意义不大 ''' user_dict = { "username1": (ip1 + port1), "username2": (ip2 + port2), "username3": (ip3 + port3), } # 可以在每个端都存这样一个对照表,根据ip与port就可以知道用户名了 ''' client.sendto(msg.encode('utf-8'), server_address) data, server_addr = client.recvfrom(1024) # server_addr 收到消息的服务端地址 print(data.decode('utf-8')) # 各个窗口的控制台输入与输出 # >>>:helo # hi # >>>: # >>>:aha # haa # >>>:jason nnn # jj # >>>: # >>>:hello world # ha # >>>:是给服务端用的( 客户端还是用socket模块 ),可以保持连接
服务器端
import socketserver # 文件名不要和模块冲突了,不然都不知道导哪个了 class MyServer(socketserver.BaseRequestHandler): def handle(self): # 与客户端进行通信 # print("来啦 老弟") while True: # 需要保持通信(后续 client.send() 可没有附带服务器地址, connect 被关闭了) 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() # 启动该服务对象 # ('127.0.0.1', 14327) # dAddA # ('127.0.0.1', 14326) # ADD # ('127.0.0.1', 14325) # ADsafga客户端
# TCP 实现UDP import socket client = socket.socket() client.connect(('127.0.0.1', 8080)) while True: res = input(">>>:") client.send(res.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8')) # 窗口1 控制台数据(输入与输出) # >>>:dAddA # DADDA # >>>: # 窗口2 控制台数据(输入与输出) # >>>:ADD # ADD # >>>: # 窗口1 控制台数据(输入与输出) # >>>:ADsafga # ADSAFGA # >>>:服务器端
import socketserver # 文件名不要和模块冲突了,不然都不知道导哪个了 class MyServer(socketserver.BaseRequestHandler): def handle(self): # 与客户端进行通信 # while True: # UDP 不需要通信循环,每次 sendto 都有服务器的地址 data, sock = self.request print(self.client_address) # 客户端地址 print(data.decode('utf-8')) sock.sendto(data.lower(), self.client_address) if __name__ == '__main__': '''只要有客户端连接,会自动交给自定义类中的handle方法去处理''' server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyServer) # 创建一个基于UDP的对象 server.serve_forever() # 启动该服务对象 # 控制台打印的数据 # ('127.0.0.1', 52524) # CLient2 # ('127.0.0.1', 52529) # clet1 # ('127.0.0.1', 52529) # CLienT1 # ('127.0.0.1', 54485) # CLiEnt3客户端
import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addr = ('127.0.0.1', 8080) while True: res = input(">>>:").strip() client.sendto(res.encode('utf-8'), server_addr) data, response_server_addr = client.recvfrom(1024) print(data.decode('utf-8'), response_server_addr) # 窗口1 控制台数据(输入与输出) # >>>:clIeNt1 # clet1 ('127.0.0.1', 8080) # >>>:CLienT1 # client1 ('127.0.0.1', 8080) # >>>: # 窗口2 控制台数据(输入与输出) # >>>:CLient2 # client2 ('127.0.0.1', 8080) # >>>: # 窗口1 控制台数据(输入与输出) # >>>:CLiEnt3 # client3 ('127.0.0.1', 8080) # >>>: handle 是处理一次连接请求的,handle结束连接就断开了
UDP是不需要保持(双向)连接的,所以每次sendto 都是单个请求(都附带服务器端地址及端口),不能写通信循环(不然就拿着一个sendto 过来的数据循环打印了)
而TCP是基于双向通道通信的,handle结束后连接就断开了(再client.send() 这个连接状态就已经不存在了),所以TCP这边的服务端要写通信循环保持连接来多次通信
转载于:https://www.cnblogs.com/PowerTips/p/11322071.html