zoukankan      html  css  js  c++  java
  • python 网络编程粘包解决方案2 + ftp上传 + socketserver

    一。struct

    神奇的打包工具 struct 

    代码:

    import struct
    num = 156
    #将int类型的数据打包成4个字节的数据
    num_stru = struct.pack('i',num)
    print(len(num_stru))
    print(num_stru)
    print('11111111111111111111111111111111')
    
    #在通过int类型解包,将前面打包的数据解包成打包之前的int数据
    num2 = struct.unpack('i',num_stru) #解包出来是个元组
    print(num2)#(156,)
    print(num2[0])

    粘包的另一种情况: .第一次服务端发送的数据比我客户端设置的一次接收消息的大小要大,那么接收不完,第二次再接收的时候,就会将第一次剩余的消息接收到

    处理粘包情况的方案二:

    代码:

    服务端

    import socket
    import subprocess
    import struct
    server = socket.socket()
    ip = ('192.168.15.142',8003)
    server.bind(ip)
    server.listen()
    
    coon,addr = server.accept()
    while 1:   from_client_msg
    = coon.recv(1024).decode('utf-8')   sub_obj = subprocess.Popen(from_client_msg,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)   server_cmd_msg = sub_obj.stdout.read()   cmd_msg_len = len(server_cmd_msg)   msg_len_stru = struct.pack('i',cmd_msg_len)   coon.send(msg_len_stru)   coon.sendall(server_cmd_msg)

    客户端

    import struct
    import socket
    
    client = socket.socket()
    server_ip = ('192.168.15.142',8003)
    client.connect(server_ip)
    while 1:
        msg = input('请输入指令:')
        client.send(msg.encode('utf-8'))
    
        from_server_msglen = client.recv(4)
        unpack_len_msg = struct.unpack('i',from_server_msglen)[0]
    
        recv_msg_len = 0
        all_msg = b''
        while recv_msg_len < unpack_len_msg:
            every_recv_data = client.recv(1024)
    
            all_msg += every_recv_data
            recv_msg_len += len(every_recv_data)
        print(all_msg.decode('gbk'))

    二。 ftp 上传方案代码:

     代码:

    简单版ftp上传服务端示例:

    import socket
    import struct
    import json
    import os
    tcp_server = socket.socket()
    ip_port = ('127.0.0.1',8001) #127.0.0.1本机的回环地址,供内部程序之间测试用的
    tcp_server.bind(ip_port)
    tcp_server.listen()
    #客户端上传的文件路径,都放在这个路径下
    client_file_path = r'D:jj'
    
    conn,addr = tcp_server.accept()
    #首先接收到文件信息长度转换出来的4个字节的数据
    file_info_stru = conn.recv(4)
    #解包文件信息的长度
    file_info_len = struct.unpack('i',file_info_stru)[0]
    #然后接收文件的描述信息
    client_file_info = conn.recv(file_info_len).decode('utf-8')
    #将接收到的json字符串反序列化
    abc_file_info = json.loads(client_file_info)
    print('abc_file_info>>>',abc_file_info)
    client_file_size = abc_file_info['file_size']
    
    recv_all_size = 0
    
    #拼接一下全路径
    client_full_path = client_file_path + '\' + abc_file_info['file_name']
    # client_full_path = os.path.join(client_file_path,abc_file_info['file_name'])
    with open(client_full_path,'wb') as f:
        while recv_all_size < client_file_size:
            every_recv_data = conn.recv(1024)
            f.write(every_recv_data)
            recv_all_size += len(every_recv_data)
    
    
    conn.send('小伙玩的行,上传成功!'.encode('utf-8'))
    conn.close()
    tcp_server.close()

    简单版ftp上传客户端示例:

    import socket
    import struct
    import os
    import json
    
    tcp_client = socket.socket()
    server_ip_port = ('127.0.0.1',8001)
    tcp_client.connect(server_ip_port)
    read_size = 1024
    
    
    file_info = {
        'file_path':r'D:python_workspaceday030aaa.mp4',
        'file_name':'aaa.mp4',
        'file_size':None,
    }
    
    #获取文件大小
    file_size = os.path.getsize(file_info['file_path'])
    
    #将文件大小添加到文件信息的字典中
    file_info['file_size'] = file_size
    #因为我们要发送的数据是字节类型,那么必须将字典转换为bytes类型,但是字典不能直接转换为bytes,所以我们想到了json,
    #通过json模块将字典类型的文件信息数据转换为了json类型的字符串
    file_info_json = json.dumps(file_info)
    #获取了字符串的长度
    file_info_len = len(file_info_json)
    #将长度打包为4个字节的数据,
    file_info_stru = struct.pack('i',file_info_len)
    #将打包好的4个自己的数据和我的文件信息数据一起发送给了服务端
    tcp_client.send(file_info_stru)
    tcp_client.send(file_info_json.encode('utf-8'))
    
    #统计文件数据
    all_file_data = b''
    #统计文件数据长度
    all_size_len = 0
    
    with open(file_info['file_path'],'rb') as f:
        while all_size_len < file_size:
            every_read_data = f.read(read_size)
            all_file_data += every_read_data
            all_size_len += len(every_read_data)
            #发送每次读取的数据
            tcp_client.send(every_read_data)
    
    print(tcp_client.recv(1024).decode('utf-8'))
    tcp_client.close()

    三。socketserver

    作用:能够让服务端和多个客户端交互

    代码:

    服务端

    import socketserver
    
    #1 定义一个类
    class MyServer(socketserver.BaseRequestHandler): #2 类里面继承socketserver.BaseRequestHandler
        # 3 类里面定义一个handle方法,handle名称不能变
        def handle(self):
            while 1:
            # self.request      #conn链接通道
                from_client_data = self.request.recv(1024).decode('utf-8')
                print(from_client_data)
                server_input = input('明巍sb说>>>')
                self.request.send(server_input.encode('utf-8'))
            # self.request.close()
    if __name__ == '__main__':
        #服务端的IP地址和端口
        ip_port = ('127.0.0.1',8001)
        socketserver.TCPServer.allow_reuse_address = True
        #绑定IP地址和端口,并且启动我定义的上面这个类
        server = socketserver.ThreadingTCPServer(ip_port,MyServer)
        #永久的给我执行下去
        server.serve_forever()

    客户端

    import socket
    
    tcp_client = socket.socket()
    server_ip_port = ('127.0.0.1',8001)
    tcp_client.connect(server_ip_port)
    while 1:
        client_msg = input('大阳哥>>>')
        tcp_client.send(client_msg.encode('utf-8'))
        from_server_msg = tcp_client.recv(1024).decode('utf-8')
        print(from_server_msg)
  • 相关阅读:
    Redis数据结构
    PostgreSQL中的onflict
    Lombok注解
    Kafka基本介绍
    Java8特性
    Java8特性Lambda表达式
    网络经济与企业管理(第10章:供应链管理)
    网络经济与企业管理(第9章:企业知识管理)
    网络经济与企业管理(第8章:人力资源管理)
    网络经济与企业管理(第7章:企业财务管理)
  • 原文地址:https://www.cnblogs.com/qq1426794755/p/9811449.html
Copyright © 2011-2022 走看看