Python3使用TCP编写一个简易的文件下载器功能


Posted in Python onMay 08, 2019

利用Python3来实现TCP协议,和UDP类似。UDP应用于及时通信,而TCP协议用来传送文件、命令等操作,因为这些数据不允许丢失,否则会造成文件错误或命令混乱。下面代码就是模拟客户端通过命令行操作服务器。客户端输入命令,服务器执行并且返回结果。

TCP(Transmission Control Protocol 传输控制协议):是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

使用TCP编写一个简易的文件下载器要求:需编写文件下载器服务端和文件下载器客户端

服务器端代码:

import socket
import os
import threading
# 处理客户端请求下载文件的操作(从主线程提出来的代码)
def deal_client_request(ip_port, service_client_socket):
  # 连接成功后,输出“客户端连接成功”和客户端的ip和端口
  print("客户端连接成功", ip_port)
  # 接收客户端的请求信息
  file_name = service_client_socket.recv(1024)
  # 解码
  file_name_data = file_name.decode("utf-8")
  # 判断文件是否存在
  if os.path.exists(file_name_data):
    #输出文件字节数
    fsize = os.path.getsize(file_name_data)
    #转化为兆单位
    fmb = fsize/float(1024*1024)
    #要传输的文件信息
    senddata = "文件名:%s 文件大小:%.2fMB"%(file_name_data,fmb)
    #发送和打印文件信息
    service_client_socket.send(senddata.encode("utf-8"))
    print("请求文件名:%s 文件大小:%.2f MB"%(file_name_data,fmb))
    #接受客户是否需要下载
    options = service_client_socket.recv(1024)
    if options.decode("utf-8") == "y":
      # 打开文件
      with open(file_name_data, "rb") as f:
        # 计算总数据包数目
        nums = fsize/1024 
        # 当前传输的数据包数目
        cnum = 0
        while True:
          file_data = f.read(1024)
          cnum = cnum + 1
          jindu = cnum/nums*100
          print("当前已下载:%.2f%%"%jindu,end = "\r")
          if file_data:
            # 只要读取到数据,就向客户端进行发送
            service_client_socket.send(file_data)
          # 数据读完,退出循环
          else:
            print("请求的文件数据发送完成")
            break
    else:
      print("下载取消!")
  else:
    print("下载的文件不存在!")
  # 关闭服务当前客户端的套接字
  service_client_socket.close()
if __name__ == '__main__':
  # 把工作目录切换到data目录下
  os.chdir("./data")
  # 创建套接字
  tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  # 绑定端口号
  tcp_server_socket.bind(("", 3356))
  # 设置监听,将主动套接字变为被动套接字
  tcp_server_socket.listen(128)
  # 循环调用accept,可以支持多个客户端同时连接,和多个客户端同时下载文件
  while True:
    service_client_socket, ip_port = tcp_server_socket.accept()
    # 连接成功后打印套接字号
    #print(id(service_client_socket))
    # 创建子线程
    sub_thread = threading.Thread(target=deal_client_request, args=(ip_port, service_client_socket))
    # 启动子线程
    sub_thread.start()

客户端代码:

# 多任务文件下载器客户端
import socket
if __name__ == '__main__':
  # 创建套接字
  tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  # 和服务端连接
  server_ip = input("输入服务器IP:")
  tcp_client_socket.connect((server_ip, 3356))
  # 发送下载文件的请求
  file_name = input("请输入要下载的文件名:")
  # 编码
  file_name_data = file_name.encode("utf-8")
  # 发送文件下载请求数据
  tcp_client_socket.send(file_name_data)
  # 接收要下载的文件信息
  file_info = tcp_client_socket.recv(1024)
  # 文件信息解码
  info_decode = file_info.decode("utf-8")
  print(info_decode)
  #获取文件大小
  fileszie = float(info_decode.split(':')[2].split('MB')[0])
  fileszie2 = fileszie*1024
  # 是否下载?输入y 确认 输入q 取消
  opts = input("是否下载?(y 确认 q 取消)")
  if opts == 'q':
    print("下载取消!程序退出")
  else:
    print("正在下载 》》》")
    #向服务器确认正在下载
    tcp_client_socket.send(b'y')
    # 把数据写入到文件里
    with open("./" + file_name, "wb") as file:
      #目前接收到的数据包数目
      cnum = 0
      while True:
        # 循环接收文件数据
        file_data = tcp_client_socket.recv(1024)
        # 接收到数据
        if file_data:
          # 写入数据
          file.write(file_data)
          cnum = cnum+1
          jindu =cnum/fileszie2*100
          print("当前已下载:%.2f%%"%jindu,end = "\r")
        # 接收完成
        else:
          print("下载结束!")
          break
  # 关闭套接字
  tcp_client_socket.close()

运行窗口如下:

1)服务器端

Python3使用TCP编写一个简易的文件下载器功能

2)客户端

Python3使用TCP编写一个简易的文件下载器功能

注意:客户端和服务器端不要运行在IDLE中,直接使用终端运行。

总结

以上所述是小编给大家介绍的Python3使用TCP编写一个简易的文件下载器功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python在windows和linux下获得本机本地ip地址方法小结
Mar 20 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
Apr 20 Python
Python中文竖排显示的方法
Jul 28 Python
深入解析Python设计模式编程中建造者模式的使用
Mar 02 Python
Python设置默认编码为utf8的方法
Jul 01 Python
python实现FTP服务器服务的方法
Apr 11 Python
python 输出所有大小写字母的方法
Jan 02 Python
在python中对变量判断是否为None的三种方法总结
Jan 23 Python
Python实现一个带权无回置随机抽选函数的方法
Jul 24 Python
使用Keras预训练模型ResNet50进行图像分类方式
May 23 Python
django前端页面下拉选择框默认值设置方式
Aug 09 Python
python time()的实例用法
Nov 03 Python
详解Python的三种可变参数
May 08 #Python
Python数据类型之Tuple元组实例详解
May 08 #Python
基于腾讯云服务器部署微信小程序后台服务(Python+Django)
May 08 #Python
python中正则表达式与模式匹配
May 07 #Python
详解Python3网络爬虫(二):利用urllib.urlopen向有道翻译发送数据获得翻译结果
May 07 #Python
python对象与json相互转换的方法
May 07 #Python
python使用threading.Condition交替打印两个字符
May 07 #Python
You might like
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
Memcached常用命令以及使用说明详解
2013/06/27 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
PHP进程通信基础之信号
2017/02/19 PHP
详解yii2使用多个数据库的案例
2017/06/16 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
Smarty模板配置实例简析
2019/07/20 PHP
PHP+MySQL实现在线测试答题实例
2020/01/02 PHP
基于jquery的弹出提示框始终处于窗口的居中位置(类似于alert弹出框的效果)
2011/09/28 Javascript
js 一个关于图片onload加载的事
2013/11/10 Javascript
调试代码导致IE出错的避免方法
2014/04/04 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
2015/12/25 Javascript
jquery——九宫格大转盘抽奖实例
2017/01/16 Javascript
Webpack path与publicPath的区别详解
2018/05/03 Javascript
使用angular-cli webpack创建多个包的方法
2018/10/16 Javascript
[01:09:40]Newbee vs Pain 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[04:14]从西雅图到上海——玩家自制DOTA2主题歌曲应援TI9
2019/07/11 DOTA
Python 基于Twisted框架的文件夹网络传输源码
2016/08/28 Python
请不要重复犯我在学习Python和Linux系统上的错误
2016/12/12 Python
Python随机生成手机号、数字的方法详解
2017/07/21 Python
pycharm远程开发项目的实现步骤
2019/01/20 Python
python中for循环把字符串或者字典添加到列表的方法
2019/07/20 Python
用Python配平化学方程式的方法
2019/07/20 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
canvas裁剪clip()函数的具体使用
2018/03/01 HTML / CSS
美国杰西潘尼官网:JCPenney
2019/06/12 全球购物
俄罗斯第一家篮球店:StreetBall
2020/07/30 全球购物
什么是测试驱动开发(TDD)
2012/02/15 面试题
网站创业计划书
2014/04/30 职场文书
党员批评与自我批评发言
2014/10/02 职场文书
索赔员岗位职责
2015/02/15 职场文书
2016年习总书记讲话学习心得体会
2016/01/20 职场文书
原生CSS实现文字无限轮播的通用方法
2021/03/30 HTML / CSS
Python打包为exe详细教程
2021/05/18 Python
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
2022/02/12 Redis