• socket数据传输


    subprocess模块

    • 可以通过代码执行操作系统的终端命令

    • 返回终端命令后的结果

    import subprocess
    
    cmd = inpuy('>>>:  ').strip()
    obj = subprocess.Popen(
    cmd,
    shell=True,
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE,
    #stdin = input())
    #ipconfig --> 网络设置    
    # taskliet --> 进程列表   
    result = obj.stuout.read() + obj.stuerr.read()
    
    # windows操作系统 --》 gbk编码
        
    print(result.decode('gbk'))
    

    struct模块:

    • 将一个长的数据,压缩成固定的长度的一个标记(数据报头)

    • 客服端struct压缩包头,服务端解压缩,获取数据正式长度

    import struct
    
    #打包 ,解包
    salt = '一i个字符串'
    #客服端压缩包,先压缩头部,在发送内容
    header = struct.pack('i',len(salt))
    print(header)
    print(len(header))
    
    #服务端解包, 
    data = struct.unpack('i',header)
    print(data)
    print(data[0]) # --->返回一个元组格式
    
    #server
    import socket
    import subprocess
    import struct
    
    server = socket.socket()
    
    server.bind(
        ('127.0.0.1', 9527)
    )
    
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
    
        while True:
            try:
                # recv的数据是从内存中获取
                cmd = conn.recv(1024).decode('utf-8')
    
                if cmd == 'q':
                    break
    
                if len(cmd) == 0:
                    continue
    
                print(cmd)
    
                # 执行cmd命令
                obj = subprocess.Popen(
                    cmd,
                    shell=True,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                )
    
                # 接收终端返回的数据
                result = obj.stdout.read() + obj.stderr.read()
    
                # 打包压缩,获取报头
                headers = struct.pack('i', len(result))
    
                # 先发送头部
                conn.send(headers)
    
                # 再发送真实数据
                conn.send(result)
    
            except Exception as e:
                print(e)
                break
        conn.close()
                
                
    
    # client
    import socket
    import struct
    
    client = socket.socket()
    
    client.connect(
        ('127.0.0.1', 9527)
    )
    
    while True:
    
        cmd = input('》》》:')  # dir
    
        client.send(cmd.encode('utf-8'))
    
        if cmd == 'q':
            break
    
        # 先获取数据报头
        headers = client.recv(4)
    
        # 解包,或者真实数据长度
        data_len = struct.unpack('i', headers)[0]  # (len, )
    
        # 接收真实数据长度
        data = client.recv(data_len)
    
        print(data.decode('gbk'))
    
    client.close()
    

    粘包问题:

    -粘包问题 : -无法判断传输包的长度大小

    -tcp 协议特性(流式协议): 多次发送数据量小,时间间隔时间短。

    ​ 一次性接收数据.内存浪费

    • 解决问题:

      • struct 模块 : 创建头部和内容

    QQ聊天的实现:

    #UDP 实现
    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)
        print(msg)
        print(msg1)
        
        send_msg = input('>>: ').strip()
        server.sendto(send_msg,addr)
        server.sendto(send_msg,addr1)
    
    #client
    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    server_ip_port = ('127.0.0.1',9527)
    
    while True:
        send_msg = input('>>>').strip()
        
        client.sendto(send_msg,server_ip_port)
        #接受任何人的消息
        msg = client.recv(1024)
        print(msg.decode('utf-8'))
    

    文件的传输:

    #server
    # json --> 编码  --- 》bytes
    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()
        while True:
            try:
                #接受头部
                header = conn.recv(4)
                data_len = struct.unpack('i',header)[0]
                
                bytes_data = conn.recv(data_len)
                back_dic = json.loads(bytes_data.decode('utf-8'))
                print(back_dic)
            except Exception as e:
                print(e)
                break
    conn.close()
    
    #client
    import socket
    import json
    import struct
    import time
    
    client = socket.socket()
    client.connect(('127.0.0.1',9527))
    
    while True:
        send_sic ={
            'file_name ': 'python视频',
            'file_size ': '55000',
        }
        json_data = json.dumps(send_dic)
        bytes_data = json_data.encode('utf-8')
        
        header = struct.pack('i',len(bytes_data))
        client.send(header)
        client.send(bytes_data)
        time.sleep(2)
    client.close()
    

    大文件的传输:

    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)
    
    
    client.close()
    

    传输层协议:

    TCP :

    -是一种流式协议,一段段数据流的形式传输数据

    -会将多次连续发送数据量小,并且时间隔断的数据一次性打包发送

    -数据安全,但是占网络资源大

    UDP:

    -传输协议

    -不需要建立双向管道

    -不会粘包

    -客服端发数据给服务端,不需要等待服务器返回接收成功

    -数据容易丢失,数据不安全

    --UDP : 好比在发消息

    --TCP : 好比在打电话

    #UDP 的使用
    import socket
    server = socket.socket(type = socket.SOCK_DGRAM)
    server.bind(('127.0.0.1',9527))
    
    #TCP:
    #conn,addr = server.accept()
    #conn.recv()
    
    #UDP
    msg,addr = server.recvfrom(1024)
    print(msg)
    
    #client
    
    import socket
    client = socket.socket(type = socket.SOCK_DGRAM)
    SERVER_IP_PORT = ('127.0.0.1',9527)
    client.sendto(b'hell0',SERVER_IP_PORT)
    
    
    client.close()
    

    FTP:

    • 包括两个组成部分,其一为FTP服务器,

      • 其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上

    socketServer模块:

    • 简化socket,服务端的代码

      • 定义类,实现

    #client
    import socket
    client = socket.socket()
    client.connent(('127.0.0.1',9527))
    
    while True:
        send_msg = input('>>>: ').striP()
        client.send(send_msg.encode('utf-8'))
        
        back_msg = client.recv(1024)
        print(back_msg.decode('utf-8'))
    
    import socketserver
    
    #定义类,继承BaseRequestHeadler类
    class MyTcpServer(socketserver.BaseRequestHeadler):
        #重写父类,子类覆盖
        def headle(self):
            print(self.client_address)
            while True:
                try:
                    #request.recv(1024) == > conn.recv(1024)
                    data = self.request.recv(1024).decode('utf-8')
                    #对接收数据处理
                    send_msg = data.upper()
                    self.request.send(send_msg.encode('utf-8'))
                exxept Exception as e:
                    print(e)
                    break
    if __name__ == '__main__':
            # socketserver.TCPServer只能有一个技师服务
        # server = socketserver.TCPServer(
        #     ('127.0.0.1', 8888), MyTcpServer
        # )
    
        # ThreadingTCPServer: 有多个技师可服务
        server = socketserver.ThreadingTCPServer(
            ('127.0.0.1', 8888), MyTcpServer
        )
    
        # 永久执行服务
        server.serve_forever()
    
           
    
    
  • 相关阅读:
    MongoDB数据库学习总结
    windows及linux环境下永久修改pip镜像源的方法
    enumerate枚举函数
    sum求和函数
    zip拉链函数
    python实现面对面快传
    redis实现发布订阅
    python自定义classmethod
    Nginx为什么支持那么高的并发量?
    java进阶(28)--Map集合
  • 原文地址:https://www.cnblogs.com/shaozheng/p/11699147.html
Copyright © 2020-2023  润新知