zoukankan      html  css  js  c++  java
  • DAY 32 UDP协议、Socketserver模块,并发编程基础

    一.粘包现象

      1.为什么会出现粘包现象

        1.只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议

        2.TCP协议的特点是将数据量小、时间间隔比较短的数据一次性打包发送

        3.粘包现象的本质是因为不知道需要接受的数据的长短

      2.如何解决粘包问题

        1.发送数据直接先告诉对方数据量的大小

        2.利用struct模块定制我们自己的消息传输协议

      3.基于TCP发送大文件示例

    # 客户端
    import struct
    import json
    import socket
    import os
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8080))
    
    file_size = os.path.getsize(r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4')
    file_path = r'/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4'
    data_dic = {
        'file_name': '澳门最大线上赌场开业啦.mp4',
        'file_size': file_size
    }
    header_json = json.dumps(data_dic)
    header_bytes = header_json.encode('utf-8')
    # 制作字典的报头
    header = struct.pack('i', len(header_bytes))
    # 发送报头
    client.send(header)
    # 发字典数据
    client.send(header_bytes)
    # 打开文件发送文件数据
    with open(file_path,'rb') as f:
        for line in f:
            client.send(line)
    
    # 服务端
    import socket
    import json
    import struct
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        while True:
            try:
                header = conn.recv(4)
                if len(header) == 0:break
                dic_len = struct.unpack('i', header)[0]
    
                real_dic = json.loads(conn.recv(dic_len).decode('utf-8'))
                print(real_dic)
                file_name = real_dic.get('file_name')
                file_size = real_dic.get('file_size')
                recv_size = 0
                with open(file_name, 'wb') as f:
                    while recv_size < file_size:
                        recv_data = conn.recv(1024)
                        f.write(recv_data)
                        recv_size += len(recv_data)
            except ConnectionResetError:
                break
    View Code

    二.UDP协议

      1.UDP协议的优点

       1.UDP协议客户端允许发空

       2.UDP协议不会粘包

       3.UDP协议服务端不存在的情况下,客户端照样不会报错

       4.UDP协议支持并发

      2.UDP协议的要求

       1.UDP协议也叫数据报协议,发送的消息都带有数据头

       2.UDP的服务端不需要进行监听也不需要建立连接

       3.服务端启动后只能被动的等待客户端发送消息,发送消息时要带上服务端地址

       4.服务端在回复消息的时候,也需要带上客户端的地址、

      示例:

    # 服务端
    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1', 8080))
    
    msg, addr = server.recvfrom(1024)
    print(msg.decode('utf-8'))
    server.sendto(b'hello', addr)
    
    server.close()
    
    #客户端
    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1', 8080)
    
    client.sendto(b'hello server baby!', server_addr)
    msg, addr = client.recvfrom(1024)
    print(msg, addr)
    View Code

      3.UDP协议特点

       1.无链接,类似于发短信,发了就行爱回不回没有任何关系

       2.将服务端关闭,客户端依旧能够发数据,不需要考虑服务端能不能收到

      4.基于UDP实现简易版本QQ

    # 服务端
    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    server.bind(('127.0.0.1', 8080))
    while True:
        msg, addr = server.recvfrom(1024)
        print(addr)
        print(msg.decode('utf-8'))
        info = input('>>>:').encode('utf-8')
        server.sendto(info, addr)
    
    server.close()
    
    # 多个客户端
    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_addr = ('127.0.0.1', 8080)
    
    while True:
        info = input('>>>:')
        info = ('来自客户端1的消息:%s'%info).encode('utf-8')  # 改中文备注即可
        client.sendto(info, server_addr)
        msg, addr = client.recvfrom(1024)
        print(msg.decode('utf-8'), addr)
    
    client.close()
    View Code

    三.socketserver模块(让TCP也能支持并发)

    # TCP socketserver使用
    import socketserver
    class MyTcpServer(socketserver.BaseRequestHandler):
        def handle(self):
            while True:
                try:
                    data = self.request.recv(1024)  # 对于tcp,self.request相当于conn对象
                    if len(data) == 0:break
                    print(data)
                    self.request.send(data.upper())
                except ConnectionResetError:
                    break
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTcpServer)
        server.serve_forever()
    
    # UDP socketserver使用
    import socketserver
    
    
    class MyUdpServer(socketserver.BaseRequestHandler):
        def handle(self):
            while True:
                data, sock = self.request
                print(data)
                sock.sendto(data.upper(), self.client_address)
    
    
    if __name__ == '__main__':
        server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpServer)
        server.serve_forever()
    View Code

    四.并发编程

      1.操作系统的发展史

       输入输出设备>>>:IO操作即(input和output)

       手工操作穿孔卡片

       批处理(磁带)

       脱机批处理系统

       一步步的优化,其实都是在提高计算机CPU利用率的问题(问题在于时串行并且没有空间上的复用)

      2.多道技术的产生

       解决cpu在执行程序,遇到io时,不干活的情况

       串行:一个程序完完整整的运行完毕,才能运行下一个程序

       并发:看上去像同时运行

       多道技术:

        1.空间上的复用(多个程序共一套硬件设备,它是多道技术实现时间上的复用的基础,不然还要去硬盘读数据)

        2.时间上的复用(单个cpu的电脑上,起多个应用程序。cpu快速切换,给人的感觉是同时运行)

        3.一个任务占用cpu时间过长或被操作系统强行剥夺走cpu的执行权限(比起串行效率反而降低)

        4.一个任务执行过程中遇到io操作,也会被操作系统强行剥夺走cpu的执行权限(比起串行效率提高)

     

  • 相关阅读:
    使用NBU进行oracle异机恢复
    mycat偶尔会出现JVM报错double free or corruption并崩溃退出
    exp导出数据时丢表
    service_names配置不正确,导致dg创建失败
    XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
    HTTP协议简介详解 HTTP协议发展 原理 请求方法 响应状态码 请求头 请求首部 java模拟浏览器客户端服务端
    java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
    【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版
    java内部类深入详解 内部类的分类 特点 定义方式 使用
    再谈包访问权限 子类为何不能使用父类protected方法
  • 原文地址:https://www.cnblogs.com/majingjie/p/10813430.html
Copyright © 2011-2022 走看看