zoukankan      html  css  js  c++  java
  • 第六章

    文件传输:

         1.简单版本   服务端

     1 import subprocess
     2 import socket
     3 import struct
     4 import json
     5 import os
     6 
     7 share_dir = r'D:路飞学城练习与作业pycharm练习6.网络编程5.文件传输简单版本servershare'  # r 取消特殊符号的意思 应该写到配置文件中
     8 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     9 phone.bind(('127.0.0.1',8080))
    10 phone.listen(5)
    11 print('strating...')
    12 while True:
    13     conn,client_addr = phone.accept()
    14     print(client_addr)
    15 
    16     while True:
    17         try:
    18             # 1.收命令
    19             res = conn.recv(8096) # b'get a.txt'
    20             if not res:break
    21             print('客户端数据:',res)
    22 
    23             # 2.解析命令 提取相应的命令参数
    24             cmds = res.decode('utf-8').split()
    25             filename = cmds[1]
    26 
    27             # 3.以读的方式打开文件,读取文件内容 发送给客户端  不知道文件的大小 还是用header_dic
    28             # 第一步:制作固定长度的报头  # 将字典转成 str 转成 bytes  用到了序列化
    29             header_dic = {
    30                 'filename':filename,
    31                 'md5':'xxxxxxx',
    32                 'file_size': os.path.getsize('%s/%s'%(share_dir,filename))
    33             }
    34             header_json = json.dumps(header_dic)
    35             header_bytes = header_json.encode('utf-8')   # 这里不知道 多长 会粘包!!
    36 
    37             # 第二步先发送报头的长度
    38             conn.send(struct.pack('i',len(header_bytes)))
    39 
    40             # 第三步:再发报头
    41             conn.send(header_bytes)
    42 
    43             # 第四部:在发真实的数据
    44             with open('%s/%s'%(share_dir,filename),'rb') as f:
    45                 # conn.send(f.read()) 一下读出来 有可能文件 很大
    46                 for line in f:
    47                     conn.send(line)  # 会粘包 连续好多个send 和一下发过去 一样的道理 但是节省内存
    48 
    49         except ConnectionResetError:
    50             break
    51     conn.close()
    52 
    53 phone.close()

    1.简单版本   客户端

     1 # -*- coding:utf-8 -*-
     2 '''
     3 思路:
     4     1.处理报头 准备发送的字典 先发报头的长度 再收报头 得到数据的长度 在收数据
     5     做字典 能容纳 很多信息量
     6     解决了:1.报头信息量少 2.i 格式有限的 解决了
     7 '''
     8 import json
     9 import socket
    10 import struct
    11 
    12 download_dir = r'D:路飞学城练习与作业pycharm练习6.网络编程5.文件传输简单版本clientdownload' # 应该写到配置文件中
    13 
    14 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    15 phone.connect(('127.0.0.1',8080))
    16 
    17 while True:
    18     # 1.发命令
    19     cmd = input('msg>>>:').strip()  # get a.txt 软件自己定义的 格式
    20     if not cmd:continue
    21     phone.send(cmd.encode('utf-8'))
    22 
    23     # 2.以写的方式打开一个新文件,接收服务端发来的文件内容写入客户的新文件
    24     # 第一步 先收报头的长度
    25     obj = phone.recv(4)
    26     header_size = struct.unpack('i',obj)[0]
    27 
    28     # 第二步:在收报头
    29     header_bytes = phone.recv(header_size)
    30 
    31     # 第三步:从报头中解析出对真实数据的描述
    32     header_json = header_bytes.decode('utf-8')
    33     header_dic = json.loads(header_json)
    34     print(header_dic)
    35     total_size = header_dic['file_size']
    36     filename = header_dic['filename']
    37 
    38     # 第四步:接收真实的数据
    39     with open('%s/%s'%(download_dir,filename),'wb') as f: # filename wb 瞬间清掉
    40         recv_size = 0
    41         while recv_size < total_size:
    42             line = phone.recv(1024)
    43             f.write(line)
    44             recv_size+=len(line)
    45             print('总大小:%s 已下载:%s'%(total_size,recv_size))  # 这里应该有个进度条 提示用户
    46 
    47 phone.close()

     2.优化版本   服务端

     1 import subprocess
     2 import socket
     3 import struct
     4 import json
     5 import os
     6 
     7 share_dir = r'D:路飞学城练习与作业pycharm练习6.网络编程5.文件传输优化版本servershare'  # r 取消特殊符号的意思 应该写到配置文件中
     8 
     9 
    10 def get(conn,cmds):
    11     filename = cmds[1]
    12 
    13     # 3.以读的方式打开文件,读取文件内容 发送给客户端  不知道文件的大小 还是用header_dic
    14     # 第一步:制作固定长度的报头  # 将字典转成 str 转成 bytes  用到了序列化
    15     header_dic = {
    16         'filename': filename,
    17         'md5': 'xxxxxxx',
    18         'file_size': os.path.getsize('%s/%s' % (share_dir, filename))
    19     }
    20     header_json = json.dumps(header_dic)
    21     header_bytes = header_json.encode('utf-8')  # 这里不知道 多长 会粘包!!
    22 
    23     # 第二步先发送报头的长度
    24     conn.send(struct.pack('i', len(header_bytes)))
    25 
    26     # 第三步:再发报头
    27     conn.send(header_bytes)
    28 
    29     # 第四部:在发真实的数据
    30     with open('%s/%s' % (share_dir, filename), 'rb') as f:
    31         # conn.send(f.read()) 一下读出来 有可能文件 很大
    32         for line in f:
    33             conn.send(line)  # 会粘包 连续好多个send 和一下发过去 一样的道理 但是节省内存
    34 
    35 def put():
    36     pass
    37 
    38 def run():
    39     phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    40     phone.bind(('127.0.0.1',8080))
    41     phone.listen(5)
    42     print('strating...')
    43     while True:
    44         conn,client_addr = phone.accept()
    45         print(client_addr)
    46 
    47         while True:
    48             try:
    49                 # 1.收命令
    50                 res = conn.recv(8096) # b'get a.txt'
    51                 if not res:break
    52                 print('客户端数据:',res)
    53 
    54                 # 2.解析命令 提取相应的命令参数
    55                 cmds = res.decode('utf-8').split()
    56                 if cmds[0] == 'get':
    57                     get(conn,cmds)
    58                 elif cmds[0] == 'put':
    59                     put(conn,cmds)
    60 
    61 
    62             except ConnectionResetError:
    63                 break
    64         conn.close()
    65 
    66     phone.close()
    67 
    68 if __name__ == "__main__":
    69     run()

    2.优化版本   客户端

     1 # -*- coding:utf-8 -*-
     2 '''
     3 思路:
     4     1.处理报头 准备发送的字典 先发报头的长度 再收报头 得到数据的长度 在收数据
     5     做字典 能容纳 很多信息量
     6     解决了:1.报头信息量少 2.i 格式有限的 解决了
     7 '''
     8 import json
     9 import socket
    10 import struct
    11 
    12 download_dir = r'D:路飞学城练习与作业pycharm练习6.网络编程5.文件传输优化版本clientdownload' # 应该写到配置文件中
    13 
    14 def get(phone,cmds):
    15     # 2.以写的方式打开一个新文件,接收服务端发来的文件内容写入客户的新文件
    16     # 第一步 先收报头的长度
    17     obj = phone.recv(4)
    18     header_size = struct.unpack('i', obj)[0]
    19 
    20     # 第二步:在收报头
    21     header_bytes = phone.recv(header_size)
    22 
    23     # 第三步:从报头中解析出对真实数据的描述
    24     header_json = header_bytes.decode('utf-8')
    25     header_dic = json.loads(header_json)
    26     print(header_dic)
    27     total_size = header_dic['file_size']
    28     filename = header_dic['filename']
    29 
    30     # 第四步:接收真实的数据
    31     with open('%s/%s' % (download_dir, filename), 'wb') as f:  # filename wb 瞬间清掉
    32         recv_size = 0
    33         while recv_size < total_size:
    34             line = phone.recv(1024)
    35             f.write(line)
    36             recv_size += len(line)
    37             print('总大小:%s 已下载:%s' % (total_size, recv_size))  # 这里应该有个进度条 提示用户
    38 
    39 def put(phone,cmds):
    40     pass
    41 
    42 def run():
    43     phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    44     phone.connect(('127.0.0.1',8080))
    45 
    46     while True:
    47         # 1.发命令
    48         inp = input('msg>>>:').strip()  # get a.txt 软件自己定义的 格式
    49         if not inp:continue
    50         phone.send(inp.encode('utf-8'))
    51 
    52         cmds = inp.split()
    53         if cmds[0] == 'get':
    54             get(phone,cmds)
    55         elif cmds[0] == 'put':
    56             put(phone,cmds)
    57 
    58     phone.close()  
    59 
    60 if __name__ == "__main__":
    61     run()

    3.面向对象版本  服务端

      1 import socket
      2 import os
      3 import struct
      4 import pickle
      5 
      6 
      7 class TCPServer:
      8     address_family = socket.AF_INET
      9     socket_type = socket.SOCK_STREAM
     10     listen_count = 5
     11     max_recv_bytes = 8192
     12     coding = 'utf-8'
     13     allow_reuse_address = False
     14     # 下载的文件存放路径
     15     down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share')
     16     # 上传的文件存放路径
     17     upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'upload')
     18 
     19     def __init__(self,server_address,bind_and_listen=True):
     20         self.server_address = server_address
     21         self.socket = socket.socket(self.address_family,self.socket_type)
     22 
     23         if bind_and_listen:
     24             try:
     25                 self.server_bind()
     26                 self.server_listen()
     27             except Exception:
     28                 self.server_close()
     29 
     30     def server_bind(self):
     31         if self.allow_reuse_address:
     32             self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
     33         self.socket.bind(self.server_address)
     34 
     35     def server_listen(self):
     36         self.socket.listen(self.listen_count)
     37 
     38     def server_close(self):
     39         self.socket.close()
     40 
     41     def server_accept(self):
     42         return self.socket.accept()
     43 
     44     def conn_close(self,conn):
     45         conn.close()
     46 
     47     def run(self):
     48         print('starting...')
     49         while True:
     50             self.conn,self.client_addr = self.server_accept()
     51             print(self.client_addr)
     52             while True:
     53                 try:
     54                     res = self.conn.recv(self.max_recv_bytes)
     55                     if not res:continue
     56                     cmds = res.decode(self.coding).split()
     57                     if hasattr(self,cmds[0]):
     58                         func = getattr(self,cmds[0])
     59                         func(cmds)
     60                 except Exception:
     61                     break
     62             self.conn_close(self.conn)
     63 
     64     def get(self,cmds):
     65         """ 下载
     66         1.找到下载的文件
     67         2.发送 header_size
     68         3.发送 header_bytes file_size
     69         4.读文件 rb 发送 send(line)
     70         5.若文件不存在,发送0 client提示:文件不存在
     71         :param cmds: 下载的文件 eg:['get','a.txt']
     72         :return:
     73         """
     74         filename = cmds[1]
     75         file_path = os.path.join(self.down_filepath, filename)
     76         if os.path.isfile(file_path):
     77             header = {
     78                 'filename': filename,
     79                 'md5': 'xxxxxx',
     80                 'file_size': os.path.getsize(file_path)
     81             }
     82             header_bytes = pickle.dumps(header)
     83             self.conn.send(struct.pack('i', len(header_bytes)))
     84             self.conn.send(header_bytes)
     85             with open(file_path, 'rb') as f:
     86                 for line in f:
     87                     self.conn.send(line)
     88         else:
     89             self.conn.send(struct.pack('i', 0))
     90 
     91     def put(self,cmds):
     92         """ 上传
     93         1.接收4个bytes  得到文件的 header_size
     94         2.根据 header_size  得到 header_bytes  header_dic
     95         3.根据 header_dic  得到 file_size
     96         3.以写的形式 打开文件 f.write()
     97         :param cmds: 下载的文件 eg:['put','a.txt']
     98         :return:
     99         """
    100         obj = self.conn.recv(4)
    101         header_size = struct.unpack('i', obj)[0]
    102         header_bytes = self.conn.recv(header_size)
    103         header_dic = pickle.loads(header_bytes)
    104         print(header_dic)
    105         file_size = header_dic['file_size']
    106         filename = header_dic['filename']
    107 
    108         with open('%s/%s' % (self.upload_filepath, filename), 'wb') as f:
    109             recv_size = 0
    110             while recv_size < file_size:
    111                 res = self.conn.recv(self.max_recv_bytes)
    112                 f.write(res)
    113                 recv_size += len(res)
    114 
    115 
    116 tcp_server = TCPServer(('127.0.0.1',8080))
    117 tcp_server.run()
    118 tcp_server.server_close()

    3.面向对象版本  客户端

      1 import socket
      2 import struct
      3 import pickle
      4 import os
      5 
      6 
      7 class FTPClient:
      8     address_family = socket.AF_INET
      9     socket_type = socket.SOCK_STREAM
     10     # 下载的文件存放路径
     11     down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'download')
     12     # 上传的文件存放路径
     13     upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share')
     14     coding = 'utf-8'
     15     max_recv_bytes = 8192
     16 
     17     def __init__(self, server_address, connect=True):
     18         self.server_address = server_address
     19         self.socket = socket.socket(self.address_family, self.socket_type)
     20         if connect:
     21             try:
     22                 self.client_connect()
     23             except Exception:
     24                 self.client_close()
     25 
     26     def client_connect(self):
     27         self.socket.connect(self.server_address)
     28 
     29     def client_close(self):
     30         self.socket.close()
     31 
     32     def run(self):
     33         while True:
     34             # get a.txt 下载   put a.txt 上传
     35             msg = input(">>>:").strip()
     36             if not msg: continue
     37             self.socket.send(msg.encode(self.coding))
     38             cmds = msg.split()
     39             if hasattr(self,cmds[0]):
     40                 func = getattr(self,cmds[0])
     41                 func(cmds)
     42 
     43     def get(self, cmds):
     44         """ 下载
     45         1.得到 header_size
     46         2.得到 header_types header_dic
     47         3.得到 file_size file_name
     48         4.以写的形式 打开文件
     49         :param cmds: 下载的内容 eg: cmds = ['get','a.txt']
     50         :return:
     51         """
     52         obj = self.socket.recv(4)
     53         header_size = struct.unpack('i', obj)[0]
     54         if header_size == 0:
     55             print('文件不存在')
     56         else:
     57             header_types = self.socket.recv(header_size)
     58             header_dic = pickle.loads(header_types)
     59             print(header_dic)
     60             file_size = header_dic['file_size']
     61             filename = header_dic['filename']
     62 
     63             with open('%s/%s' % (self.down_filepath, filename), 'wb') as f:
     64                 recv_size = 0
     65                 while recv_size < file_size:
     66                     res = self.socket.recv(self.max_recv_bytes)
     67                     f.write(res)
     68                     recv_size += len(res)
     69                     print('总大小:%s 已下载:%s' % (file_size, recv_size))
     70                 else:
     71                     print('下载成功!')
     72 
     73     def put(self, cmds):
     74         """ 上传
     75         1.查看上传的文件是否存在
     76         2.上传文件 header_size
     77         3.上传文件 header_bytes
     78         4.以读的形式 打开文件 send(line)
     79         :param cmds: 上传的内容 eg: cmds = ['put','a.txt']
     80         :return:
     81         """
     82         filename = cmds[1]
     83         file_path = os.path.join(self.upload_filepath, filename)
     84         if os.path.isfile(file_path):
     85             file_size = os.path.getsize(file_path)
     86             header = {
     87                 'filename': os.path.basename(filename),
     88                 'md5': 'xxxxxx',
     89                 'file_size': file_size
     90             }
     91             header_bytes = pickle.dumps(header)
     92             self.socket.send(struct.pack('i', len(header_bytes)))
     93             self.socket.send(header_bytes)
     94 
     95             with open(file_path, 'rb') as f:
     96                 send_bytes = b''
     97                 for line in f:
     98                     self.socket.send(line)
     99                     send_bytes += line
    100                     print('总大小:%s 已上传:%s' % (file_size, len(send_bytes)))
    101                 else:
    102                     print('上传成功!')
    103         else:
    104             print('文件不存在')
    105 
    106 
    107 ftp_client = FTPClient(('127.0.0.1',8080))
    108 ftp_client.run()
    109 ftp_client.client_close()
  • 相关阅读:
    IOS开发通过代码方式使用AutoLayout (NSLayoutConstraint + Masonry) 转载
    iOS8.0 使用Photos.framework对相册的常用操作
    iOS 通用button 上图下字
    navigationItem的设置和titleView的设置
    iOS 设置导航栏 返回按钮文字隐藏
    iOS uitableivewCell 下划线顶格
    gitlab创建项目代码:
    iOS block用作属性封装代码
    iOS实录:GCD使用小结(一)
    代码处理 iOS 的横竖屏旋转
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/9016431.html
Copyright © 2011-2022 走看看