异常处理


什么是异常?

​ 程序在运行过程中出现了不可预知的错误

​ 并且该错误没有对应的处理机制,那么就会以异常的形式表现出来

​ 造成的影响就是整个程序无法运行

异常的结构

​ 1.异常的类型

​ 2.异常的信息

​ 3.异常的位置

异常的种类

​ 分为两大类

​ 1.语法错误

​ 是你程序立刻就能解决的,这种错误是不能被容忍的

​ 语法上的错误 发现之后应该立刻解决



​ 2.逻辑错误

​ 这种错是可以被容忍的 因为一眼看不出来

​ 针对逻辑上的错误 可以采用异常处理机制进行捕获

常见的错误类型

常见的出错类型 含义
SyntaxError 语法错误
NameError 名字错误
KeyError 键不存在(推荐在字典用get取值,这样不会报这个错,get里面放两个参数,左边一个是要找的key,如果key不存在,返回右边的值)
ValueError 值错误
IndexError 索引错误

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的用处:比如在代码结束之后结束读写啥的

主动报异常

if 'bitten' == 'DSB'
pass
else:
raise TypeError('净说实话')

# 关键字raise就是主动抛出异常

断言assert

# 断言不成立直接报错

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的程序可以先启动客户端再启动服务端(客户端发数据给服务端之前都没问题)

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:

TCP与UDP之间的区别


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不需要保持连接
# 与一个客户端断开连接才会和下一个客户端建立连接
# -------------------------------------------

UDP实现简易版QQ


服务器端

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
# >>>:

socketserver模块科普


是给服务端用的( 客户端还是用socket模块 ),可以保持连接

TCP模拟UDP实现并发

服务器端

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
# >>>:

socketserver之UDP

服务器端

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)
# >>>:

为什么UDP不用写通信循环

​ handle 是处理一次连接请求的,handle结束连接就断开了

​ UDP是不需要保持(双向)连接的,所以每次sendto 都是单个请求(都附带服务器端地址及端口),不能写通信循环(不然就拿着一个sendto 过来的数据循环打印了)

​ 而TCP是基于双向通道通信的,handle结束后连接就断开了(再client.send() 这个连接状态就已经不存在了),所以TCP这边的服务端要写通信循环保持连接来多次通信

8.8 day29 异常处理 UDP通信的更多相关文章

  1. python异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-3

    异常捕获 异常:程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来 影响:整个程序无法再正常运行 异常的结构 异常的类型 NameError 异常的信息 ...

  2. 高性能 TCP & UDP 通信框架 HP-Socket v3.5.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  3. 高性能 TCP & UDP 通信框架 HP-Socket v3.5.2

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  4. 高性能 TCP & UDP 通信框架 HP-Socket v3.5.1

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  5. 高性能 TCP & UDP 通信框架 HP-Socket v3.4.1

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  6. 高性能 TCP & UDP 通信框架 HP-Socket v3.3.1

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  7. HP-SOCKET TCP/UDP通信框架库解析

    项目概述: HP-SOCKET是一套通用TCP/UDP通信框架,包括服务器.客户端.Agent组件:其目标是提供高性能.通用性.简易性.可扩展.可定制: 鉴于此,其仅实现基本的通用框架通信.数据收发功 ...

  8. .Net开发笔记(十四) 基于“泵”的UDP通信(接上篇)

    上一篇中说到了“泵”在编程中的作用以及一些具体用处,但没有实际demo,可能不好理解,这篇文章我分享一个UDP通信的demo,大概实现了类似“飞鸽传书”在局域网中文本消息和文件传输的功能.功能不全也不 ...

  9. 高性能 TCP & UDP 通信框架 HP-Socket v3.2.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

随机推荐

  1. java操作mongo

    语法正确时,字段不匹配时,Mongo并不会抛出异常,这在语句调试时需多加注意. mongo自身的时间存储格式与java中的并不是完全匹配,Mongo采用UTC格式,而java中一般为GMT格式,有个时 ...

  2. JavaScript捕获与冒泡与委托

    事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 相反的,事件冒泡是自下而上的去触发事件. 并不是所有的事件都能冒泡,以下事件不冒泡:blur.focus.load.un ...

  3. 牛逼了,教你用九种语言在JVM上输出HelloWorld

    我们在<深入分析Java的编译原理>中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode). 有 ...

  4. C语言的指针移动怎么理解

    C Primer pkus(第五版)中文版,老外写的还是很经典的,推荐给朋友们,购买地址:C primer plus 5版中文版购买 另外再推荐本书: 程序员面试宝典(第5版)第五版:程序员面试宝典( ...

  5. python实现DFA模拟程序(附java实现代码)

    DFA(确定的有穷自动机) 一个确定的有穷自动机M是一个五元组: M=(K,∑,f,S,Z) K是一个有穷集,它的每个元素称为一个状态. ∑是一个有穷字母表,它的每一个元素称为一个输入符号,所以也陈∑ ...

  6. 从7点到9点写的小程序(用了模块导入,python终端颜色显示,用了点局部和全局可变和不可变作用域,模块全是自定义)

    未完待续的小程序 要是能做的好看为啥不做的好看 在同目录下生成程序 1.程序文件 run.py from login import login from register import registe ...

  7. Ubuntu通过修改配置文件进行网络配置

    Ubuntu系统进行网络配置有的时候用图形界面不起作用,这种情况下可以直接修改某些启动脚本或配置文件 Ubuntu系统进行网络配置涉及到几个配置文件1./etc/network/interfaces ...

  8. 【转】8年!我在OpenStack路上走过的坑。。。

    8年!我在OpenStack路上走过的坑... 摘要: 2010年10月,OpenStack发布了第一个版本:上个月,发布了它的第18个版本Rocky.几年前气氛火爆,如今却冷冷清清.Rocky版本宣 ...

  9. 黑羽压测 做 API接口功能测试

    做功能测试 黑羽压测 是一款性能测试工具,但是我们也可以使用它,很方便的做 API接口功能测试 . 点击下方链接,观看 讲解视频 https://www.bilibili.com/video/av60 ...

  10. selenium Java中常见等待的几种形式

    前言 在自动化测试中,我们经常会碰到编写脚本过程中操作某个元素的时候, 需要等待页面加载完成后,才能对元素操作,否则会报错,提示页面元素不存在异常,我们需要等待元素加载完成后,才能继续操作,而Sele ...