zoukankan      html  css  js  c++  java
  • 网络编程(三) 大文件传输与UDP通信

    异常处理、UDP通信、socketserver模块

    1、UDP通信基本使用

    1、socket套接字的导入

    import socket
    server = socket.socket(type= socket.SOCK_DGRAM)
    #type不写默认是TCP协议
    

    服务端:

    2、UDP没有半连接池的概念(listen),也无双向通道,无需accept,直接通信循环

    3、接收数据有两个返回值:server.recvfrom(1024)

    data,addr = server.recvfrom(1024)
    print(data)#客户端的消息
    print(addr)#客户端的地址
    

    完整的服务端:

    import socket
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',8080))
    
    while True:
        data ,addr = server.recvfrom(1024)
        server.sendto(data.upper(),addr)
    

    4、发数据:sendto

    客户端:

    无需建立连接的操作,直接进入通信循环。但是要给一个连接地址用于发送

    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)
    

    总结UDP和TCP的区别:

    UDP相当于发短信;TCP相当于打电话

    2、UDP与TCP的4大区别

    1. UDP客户端允许发空:udp有一个报头

    2. udp协议不会粘包:

      不会粘包

      #客户端代码
      import socket
      client = socket.socket(type=socket.SOCK_DGRAM)
      
      server_address = ('127.0.0.1',8080)
      while True:
          client.sendto(b'hello',server_address)
          client.sendto(b'hello',server_address)
          client.sendto(b'hello',server_address)
      
      #服务端代码
      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 ,addr2 = server.recvfrom(1024)
      print(data)
      data ,addr3 = server.recvfrom(1024)
      print(data)
      
    3. 服务端断开的情况下,客户端不会报错:

      会一直停留在客户端的”输入“那一行。但是如果继续输入,则会报错

      ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
      

    3、udp支持并发:看上去是同时运行的。

    #服务端
    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',8080))
    
    while True:
        data ,addr = server.recvfrom(1024)#在这里接受任何向这个地址发送消息的客户端。
        server.sendto(data.upper(),addr)
    

    4、实现一个简易版本的QQ

    客户端代码

    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_address = (('127.0.0.1',8080))
    while True:
        msg = input('>>>').encode('utf-8')
        msg = '来自客户端1的信息:%s'%msg
        client.sendto(msg.encode('utf-8'),server_address)
        data,addr = 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'))
        msg = input('>>>')
        server.sendto(msg.encode('utf-8'),addr)
    

    5、socketserver模块

    5.1 让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):
            # 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()  # 启动该服务对象
    

    5.2socketserver同样支持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()  # 启动该服务对象
    
    #客户端代码
    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'))
    

    6、异常处理

    当try中存在多个错误的时候,遇到第一个错误立即停止下面的代码,直接进“except”中弹出信息

    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')
    #运行程序的结果是NameError
    
    Exception万能异常.以及else和finally
    try:
        # name
        l = [1,2,3]
        l[111]
        # d = {'name':'jason'}
        # d['password']
    except Exception:  # 万能异常  所有的异常类型都被捕获
        print('老子天下无敌')
    else:
        print('被检测的代码没有任何的异常发生 才会走else')
    finally:
        print('无论被检测的代码有没有异常发生 都会在代码运行完毕之后执行我')
    
    万能异常BaseException
    try:
        # name
        l = [1,2,3]
        l[111]
        d = {'name':'jason'}
        d['password']
        # Exception
    except BaseException:  # 万能异常  所有的异常类型都被捕获
        print('老子天下无敌')
    

    BaseException是所有异常的祖宗。父类。

    #点开源码
    Exception(BaseException)
    
    主动抛异常raise
    if 'egon' == 'DSB':
        pass
    else:    
        raise TypeError('尽说大实话')# 关键字raise就是主动抛出异常
    #命令行飘红(以下代码飘红)
    Traceback (most recent call last):
      File "C:/untitled6/32.py", line 4, in <module>
        raise TypeError('尽说大实话')
    TypeError: 尽说大实话
    
    断言assert(判断)
    l = ['a','b']
    assert len(l) < 0
    #与raise一样,运行结果飘红
    
    自定义异常
    class MyError(BaseException):
         def __init__(self,msg):
             super().__init__()
             self.msg=msg
         def __str__(self):
             return '<dfsdf%ssdfsdaf>' %self.msg
    
    raise MyError('我自己定义的异常')  # 主动抛出异常其实就是将异常类的对象打印出来,会走__str__方法
    
  • 相关阅读:
    ValueStack、ActionContext
    s debug
    1923: [Sdoi2010]外星千足虫
    1013: [JSOI2008]球形空间产生器sphere
    HDU 3923 Invoker
    poj 1286 Necklace of Beads
    HDU 3037:Saving Beans
    2440: [中山市选2011]完全平方数
    1101: [POI2007]Zap
    1968: [Ahoi2005]COMMON 约数研究
  • 原文地址:https://www.cnblogs.com/ZDQ1/p/11327940.html
Copyright © 2011-2022 走看看