zoukankan      html  css  js  c++  java
  • 异常处理和UDP Socket套接字

    一、异常处理

    1.什么是异常处理:

      程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表达出来,造成的影响就是整个程序无法再正常进行。

    2.异常的结构:

      1、异常的类型

      2、异常的信息

      3、异常的位置

    3.异常的种类分为两大类:

      1.语法错误:是你程序立刻就能解决的,这种错误是不能被容忍的,语法上的错误,发现之后应该立刻解决。

      2.逻辑错误:这种错误是可以被容忍的,因为一眼看不出来,针对逻辑上的错误,可以采用异常处理机制来进行捕获。

    4.常见的错误类型:

    NAMERROR     名字错误
    SyntaxError  语法错误
    KeyError     键不存在
    ValueError   值错误
    IndexError   索引错误

    5.如何避免异常:

      异常处理:在你认为可能会出现bug的代码块上方try一下:注意try内部的代码块越少越好。 

    try:
      可能出错的代码
    except 出错的类型 as e:     # 将报错信息赋值给变量e
      出错之后的处理机制

    try:
        name
        l = [1,2,3]
        l[111]
        d = {'name':'jason'}
        d['password']
    except NameError:
        print('NameError')
    except IndexError:
        print('indexerror')
    except KeyError:
        print('keyerror')
    except BaseException:  # 万能异常  所有的异常类型都被捕获
    print('老子天下无敌')
    """ 错误发生之后 会立刻停止代码的运行执行except语句 比对错误类型 """

    当try中的代码块没有检测到异常时候,就会走else代码,finally无论有没有错误最后都会走。

    try:
        name
        l = [1,2,3]
        l[111]
        d = {'name':'jason'}
        d['password']
    except Exception:  # 万能异常  所有的异常类型都被捕获
        print('老子天下无敌')
    else:
        print('被检测的代码没有任何的异常发生 才会走else')
    finally:
        print('无论被检测的代码有没有异常发生 都会在代码运行完毕之后执行我')

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

    if 'egon' == 'DSB':
        pass
    else:
        raise TypeError('尽说大实话')

    7.断言   就是预言 猜某个数据的状态 猜对了不影响代码执行正常走,猜错了直接报错

    l = [1,2,3]
    assert len(l) < 0 

    8.自定义异常   继承BaseException

    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通信   udp是无链接的,启动服务之后可以直接接收消息,不需要提前建立连接

      数据报协议(自带报头)

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

      TCP通道类似于打电话

    server端    注意在创建对象时要注定类型type,要进行设置(******)

    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)  # UDP协议
    server.bind(('127.0.0.1',8080))
    # UDP不需要设置半连接池 它也没有半连接池的概念
    
    # 因为没有双向通道  不需要accept  直接就是通信循环
    while True:
        data, addr = server.recvfrom(1024)  #UDP接收是recvfrom,返回两个值
        print('数据:',data)  # 客户端发来的消息
        print('地址:',addr)  # 客户端的地址
        server.sendto(data.upper(),addr)  #UDP是sendto,发送两个值

    client端

    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)

    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'))
        msg = input('>>>:')
        server.sendto(msg.encode('utf-8'),addr)

    客户端1

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_address = ('127.0.0.1',8080)
    
    while True:
        msg = input('>>>:')
        msg = '来自客户端1的消息:%s'%msg
        client.sendto(msg.encode('utf-8'),server_address)
        data, server_addr = client.recvfrom(1024)
        print(data.decode('utf-8'))

    客户端2

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_address = ('127.0.0.1',8080)
    
    while True:
        msg = input('>>>:')
        msg = '来自客户端2的消息:%s'%msg
        client.sendto(msg.encode('utf-8'),server_address)
        data, server_addr = client.recvfrom(1024)
        print(data.decode('utf-8'))

    客户端3

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_address = ('127.0.0.1',8080)
    
    while True:
        msg = input('>>>:')
        msg = '来自客户端3的消息:%s'%msg
        client.sendto(msg.encode('utf-8'),server_address)
        data, server_addr = client.recvfrom(1024)
        print(data.decode('utf-8'))

    总结:UDP的scoket服务端能同时和多个客户端进行数据传输,因为UDP是无链接的,之间是没有双向通道的,只要知道地址和传输内容就能进行互相传输。TCP的scoket服务端一次只能服务一个客户端,必须等访问的客户端关闭才能访问下一个客户端。

    三、TCP与UDP之间的区别

    服务端

    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_address = ('127.0.0.1',8080)
    
    client.sendto(b'hello',server_address)
    client.sendto(b'hello',server_address)
    client.sendto(b'hello',server_address)

    打印结果  (不会粘包)

    基于以上的总结:

      1.udp协议客户端允许发空     (TCP客户端如果传送内容为空,客户端和服务端就会夯在那,两边都处在接收状态,不会往下运行)

      2.udp协议不会粘包  (只有TCP有粘包现象,UDP永远不会粘包)  为什么会出现粘包,在上一篇中讲到

      3.udp协议服务端不存在的情况下,客户端照样不会报错    (因为在启动时候,客户端和服务端并没有进行连接)

      4.udp协议支持并发     并发:看起来像同时运行的

     四、socketserver模块  

    应用了socketserver   在TCP中也可以实时和多个客户端进行交互了

    服务端

    import socketserver
    
    class MyServer(socketserver.BaseRequestHandler):
        def handle(self):    
            while True:
                data = self.request.recv(1024)   #self.request  相当于conn
                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()  # 启动该服务对象

    客户端

    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'))
  • 相关阅读:
    Sublime Text 包管理工具及扩展大全
    MVC5路由系统机制详细讲解
    Asp.net MVC中Html.Partial, RenderPartial, Action,RenderAction 区别和用法【转发】
    解决Html.CheckBoxFor中”无法将类型 bool 隐式转换为 bool。存在一个显式转换..."的方法
    [C#]List的Sort()、Find()、FindAll()、Exist()的使用方法举例
    jqGrid配置属性说明
    MSSQL查找前一天,前一月,前一年的数据,对比当前时间记录查找超过一年,一月,一天的数据
    【转】linux expr命令参数及用法详解
    ls -alrth 及ls 详解
    修改linux文件权限命令:chmod
  • 原文地址:https://www.cnblogs.com/wangcuican/p/11321744.html
Copyright © 2011-2022 走看看