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 探针的实现原理
Apr 23 Python
Python 编码处理-str与Unicode的区别
Sep 06 Python
python批量读取txt文件为DataFrame的方法
Apr 03 Python
Python3.4学习笔记之列表、数组操作示例
Mar 01 Python
使用python实现unix2dos和dos2unix命令的例子
Aug 13 Python
如何基于Python获取图片的物理尺寸
Nov 25 Python
Pycharm远程连接服务器并实现代码同步上传更新功能
Feb 25 Python
Python发送邮件封装实现过程详解
May 09 Python
使用Keras实现Tensor的相乘和相加代码
Jun 18 Python
Python __slots__的使用方法
Nov 15 Python
python飞机大战游戏实例讲解
Dec 04 Python
python基于opencv批量生成验证码的示例
Apr 28 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
Get或Post提交值的非法数据处理
2006/10/09 PHP
memcached 和 mysql 主从环境下php开发代码详解
2010/05/16 PHP
PHP+Mysql+jQuery实现发布微博程序 jQuery篇
2011/10/08 PHP
PHP 杂谈《重构-改善既有代码的设计》之四 简化条件表达式
2012/04/09 PHP
php获取参数的几种方法总结
2014/02/18 PHP
PHP处理Oracle的CLOB实例
2014/11/03 PHP
PHP动态编译出现Cannot find autoconf的解决方法
2014/11/05 PHP
PHP比你想象的好得多
2014/11/27 PHP
什么是PEAR?什么是PECL?PHP中两个容易混淆的概念解释
2015/07/01 PHP
php 实现Hash表功能实例详解
2016/11/29 PHP
jQuery ui 1.7更新小结
2009/08/15 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
2010/04/01 Javascript
js实现表格字段排序
2014/02/19 Javascript
js获取当前地址 JS获取当前URL的示例代码
2014/02/26 Javascript
JS基于面向对象实现的放烟花效果
2015/05/07 Javascript
jquery图片滚动放大代码分享(1)
2015/08/25 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
2015/09/22 Javascript
JavaScript  cookie 跨域访问之广告推广
2016/04/20 Javascript
简单实现JavaScript图片切换效果
2016/11/28 Javascript
Canvas实现放射线动画效果
2017/02/15 Javascript
JS实现图片放大缩小的方法
2017/02/15 Javascript
js使用原型对象(prototype)需要注意的地方
2017/08/28 Javascript
Webpack中publicPath路径问题详解
2018/05/03 Javascript
微信小程序使用map组件实现获取定位城市天气或者指定城市天气数据功能
2019/01/22 Javascript
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
2020/02/12 Javascript
nodejs使用socket5进行代理请求的实现
2020/02/21 NodeJs
[02:22:36]《加油!DOTA》总决赛
2014/09/19 DOTA
python实现五子棋游戏(pygame版)
2020/01/19 Python
python用pip install时安装失败的一系列问题及解决方法
2020/02/24 Python
基于pandas向csv添加新的行和列
2020/05/25 Python
python给视频添加背景音乐并改变音量的具体方法
2020/07/19 Python
东南亚排名第一的服务市场:kaodim
2019/03/28 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
学历公证委托书
2014/04/09 职场文书
2014年中秋节活动总结
2014/08/29 职场文书
计算机考试作弊检讨书1000字
2015/01/01 职场文书