zoukankan      html  css  js  c++  java
  • day 27小结

    subprocess模块

    1.可以帮你通过代码执行操作系统的终端命令。

    2.并返回终端执行命令后的结果。

    import subprocess
    
    cmd = input('cmd>>:')  # dir
    
    obj = subprocess.Popen(
        # cmd命令
        cmd,
        # Shell=True
        shell=True,
        # 返回正确结果参数
        stdout=subprocess.PIPE,
        # 返回错误结果参数 error
        stderr=subprocess.PIPE
    )
    
    result = obj.stdout.read() + obj.stderr.read()
    
    print(result.decode('gbk'))
    

    粘包问题

    ​ 服务端第一次发送的数据,客户端无法精确一次性接受完毕.

    ​ 下一次发送的数据与上一次数据粘在了一起

    ​ 1.无法预测对方需要接受的数据大小长度

    ​ 2.多次连续发送数据量小,并且时间间隔短的数据一次性打包发送

    ​ TCP协议特性:

    ​ tcp是一个流式协议,会将多次连续发送数据量小,并且时间间隔短的数据一次性打包发送

    -- 解决粘包问题:

    ​ -- struct模块

    ​ 是一个可以将很长的数据的长度,压缩成固定的长度的一个标记(数据报头)

    ​ 必须先定义报头,再发送真实数据

    ​ -- 既想发送文件,又想发送文件的描述信息

    import struct
    # 客户端发送字典给服务端
    send_dic ={
    		file_name: tank.txt
    		file_size: 文件真实长度
    }
    # 通过json模块序列化成bytes数据
    json_data = json.dumps(send_dic)
    bytes_data = json_data.encode('utf8') #  bytes
    
    # 先获取字典的报头
    headers = struct.pack('i',len(bytes_data))
    
    # 服务端接收到字典,并接收文件的真实数据
    

    上传大文件

    ​ 客户端往服务器上传大文件

    # 服务端
    import socket
    import json
    import struct
    server = socket.socket()
    server.bind(
        ('127.0.0.1', 9527)
    )
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        try:
            # 先接收字典报头
            headers = conn.recv(4)
    
            # 解包获取字典真实数据长度
            data_len = struct.unpack('i', headers)[0]
    
            # 获取字典真实数据
            bytes_data = conn.recv(data_len)
    
            # 反序列得到字典
            back_dic = json.loads(bytes_data.decode('utf-8'))
    
            print(back_dic)
    
            # 拿到字典的文件名,文件大小
            file_name = back_dic.get('file_name')
            file_size = back_dic.get('file_size')
    
            init_data = 0
            # 1.以文件名打开文件,准备写入
            with open(file_name, 'wb') as f:
    
                # 一点一点接收文件,并写入
                while init_data < file_size:
                    data = conn.recv(1024)
                    # 2.开始写入视频文件
                    f.write(data)
                    init_data += len(data)
    
                print(f'{file_name}接收完毕!')
    
        except Exception as e:
            print(e)
            break
    
    conn.close()
    
    
    # 客户端
    import socket
    import struct
    import json
    
    client = socket.socket()
    
    client.connect(
        ('127.0.0.1', 9527)
    )
    
    
    # 1.打开一个视频文件,获取视频数据大小
    with open(r'D:jason真实写真集.mp4', 'rb') as f:
        movie_bytes = f.read()
        # 关闭文件
    
    # 2.为视频文件组织一个字典,字典内有视频的名称,视频大小
    send_dic = {
        'file_name': 'jason真实写真集.mp4',
        'file_size': len(movie_bytes)  # 10G
    }
    
    # 3.先打包字典,发送headers报头,再发送真实字典数据
    json_data = json.dumps(send_dic)
    bytes_data = json_data.encode('utf-8')
    headers = struct.pack('i', len(bytes_data))
    # 发送报头
    client.send(headers)
    # 发送真实字典数据
    client.send(bytes_data)
    
    # 4.接着发送真实视频文件数据
    init_data = 0
    num = 1
    with open(r'D:jason真实写真集.mp4', 'rb') as f:
        while init_data < len(movie_bytes):
            # 最后一次获取,有多少拿多少
            send_data = f.read(1024)
            print(send_data, num)
            num += 1
            # 每次发送1024数据
            client.send(send_data)
            # 为初始发送数据 + 已发送数据的长度
            init_data += len(send_data)
    

    UDP

    ​ UDP事一种传输协议

    ​ 1.不需要建立双向通道

    ​ 2.不会粘包

    ​ 3.客户端给服务端发送数据,不需要等待服务端返回接收成功

    ​ - TCP: 就好比在打电话

    • UDP: 就好比在发短信

      # 服务端
      import socket
      
      # SOCK_DGRAM: 代表UDP
      server = socket.socket(type=socket.SOCK_DGRAM)
      
      # 服务端需要绑定ip+port
      server.bind(
          ('127.0.0.1', 9527)
      )
      
      # TCP
      # conn, addr = server.accept()
      # conn.recv()
      
      # UDP
      msg, addr = server.recvfrom(1024)
      msg1, addr1 = server.recvfrom(1024)
      msg2, addr2 = server.recvfrom(1024)
      
      print(msg, msg1, msg2)
      
      
      
      #客户端
      import socket
      client = socket.socket(type=socket.SOCK_DGRAM)
      server_ip_port = ('127.0.0.1', 9527)
      
      client.sendto(b'hello', server_ip_port)
      client.sendto(b'hello', server_ip_port)
      client.sendto(b'hello', server_ip_port)
      client.sendto(b'hello', server_ip_port)
      client.sendto(b'hello', server_ip_port)
      
      

    QQ 聊天室

    #服务端
    import socket
    
    server = socket.socket(type=socket.SOCK_DGRAM)
    
    server.bind(
        ('127.0.0.1', 9527)
    )
    
    while True:
    
        # 服务端接收客户端传过来的消息
        msg, addr = server.recvfrom(1024)  # (消息,客户端地址)
        msg1, addr1 = server.recvfrom(1024)  # (消息,客户端地址)
        msg2, addr2 = server.recvfrom(1024)  # (消息,客户端地址)
    
        print(addr)
        print(addr1)
        print(addr2)
        print(msg.decode('utf-8'))
        print(msg1.decode('utf-8'))
        print(msg2.decode('utf-8'))
    
        # 服务端往客户端发送消息
        send_msg = input('服务端发送消息:').encode('utf-8')
        server.sendto(send_msg, addr)
        server.sendto(send_msg, addr1)
        server.sendto(send_msg, addr2)
    
    #客户端
    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    
    server_ip_port = ('127.0.0.1', 9527)
    
    while True:
        send_msg = input('客户端1: ').encode('utf-8')
    
        # 发送消息必须要加上对方地址
        client.sendto(send_msg, server_ip_port)
    
        # 能接收任何人的消息
        msg = client.recv(1024)
    
        print(msg.decode('utf-8'))
    
    
    
    

    SocketServer模块

    ​ python内置模块,可以简化socket套接字服务端的代码

    ​ - 简化TCP与UDP服务端的代码

    ​ - 必须要创建一个类

    import socketserver
    
    
    # 定义类
    # TCP: 必须继承BaseRequestHandler类
    class MyTcpServer(socketserver.BaseRequestHandler):
        # 必须重写父类的handle
        def handle(self):
    
            # 1.接收消息
            data = self.request.recv(1024)  # conn.recv(1024)
            print(data)
            # 2.给客户端发送消息
            send_msg = input('服务端: ').encode('utf-8')
            self.request.send(send_msg)
    
    
    if __name__ == '__main__':
        socketserver.TCPServer.allow_reuse_address = True
        server = socketserver.TCPServer(
            ('127.0.0.1', 8888), MyTcpServer
        )
    
        # 永久执行服务
        server.serve_forever()
    
    
    
    
  • 相关阅读:
    【UVA–11997 K Smallest Sums 】
    【LA 3027 Corporative Network】
    【bzoj3173-最长上升子序列-一题两解】
    【Rain in ACStar HDU-3340】
    【Uva 11280 飞到弗雷德里顿】
    【Uva 10269 马里奥与公主的归途】
    【Uva 11604 编码都有歧义了】
    【RevolC FaeLoN Uva 10972】
    oracle解析xml(增加对9i版本的支持)
    acl操作记录
  • 原文地址:https://www.cnblogs.com/LZF-190903/p/11708439.html
Copyright © 2011-2022 走看看