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 相关文章推荐
Python2.x中str与unicode相关问题的解决方法
Mar 30 Python
Python中利用原始套接字进行网络编程的示例
May 04 Python
Python计算一个文件里字数的方法
Jun 15 Python
举例讲解Python的lambda语句声明匿名函数的用法
Jul 01 Python
python中的字典使用分享
Jul 31 Python
基于Python pip用国内镜像下载的方法
Jun 12 Python
python截取两个单词之间的内容方法
Dec 25 Python
Python设计模式之观察者模式原理与用法详解
Jan 16 Python
Python常用模块os.path之文件及路径操作方法
Dec 03 Python
win10从零安装配置pytorch全过程图文详解
May 08 Python
Pandas读取csv时如何设置列名
Jun 02 Python
Python使用protobuf序列化和反序列化的实现
May 19 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
PHP数组操作汇总 php数组的使用技巧
2011/07/17 PHP
探讨php中防止SQL注入最好的方法是什么
2013/06/10 PHP
php中使用gd库实现远程图片下载实例
2015/05/12 PHP
浅谈PHP中的Trait使用方法
2019/03/22 PHP
javascript 特殊字符串
2009/02/25 Javascript
Jquery 学习笔记(一)
2009/10/13 Javascript
javascript控制frame,iframe的src属性代码
2009/12/31 Javascript
formvalidator验证插件中有关ajax验证问题
2013/01/04 Javascript
Jquery ajax执行顺序 返回自定义错误信息(实例讲解)
2013/11/06 Javascript
JS动态调用方法名示例介绍
2013/12/18 Javascript
js限制文本框只能输入数字方法小结
2014/06/16 Javascript
jQuery trigger()方法用法介绍
2015/01/13 Javascript
Vue.js中用webpack合并打包多个组件并实现按需加载
2017/02/17 Javascript
vue 动态改变静态图片以及请求网络图片的实现方法
2018/02/07 Javascript
详解js类型判断
2018/05/22 Javascript
Vue-cli配置打包文件本地使用的教程图解
2018/08/02 Javascript
Vue数据双向绑定的深入探究
2018/11/27 Javascript
Angular6新特性之Angular Material
2018/12/28 Javascript
Vue生命周期activated之返回上一页不重新请求数据操作
2020/07/26 Javascript
[22:20]初生之犊-TI4第5名LGD战队纪录片
2014/08/13 DOTA
Python MD5文件生成码
2009/01/12 Python
浅析Python的web.py框架中url的设定方法
2016/07/11 Python
python 数据清洗之数据合并、转换、过滤、排序
2017/02/12 Python
Python字符串格式化的方法(两种)
2017/09/19 Python
Python实现破解猜数游戏算法示例
2017/09/25 Python
使用python批量化音乐文件格式转换的实例
2019/01/09 Python
Django 配置多站点多域名的实现步骤
2019/05/17 Python
python调用matplotlib模块绘制柱状图
2019/10/18 Python
tensorflow2.0保存和恢复模型3种方法
2020/02/03 Python
matplotlib jupyter notebook 图像可视化 plt show操作
2020/04/24 Python
PyQt5通过信号实现MVC的示例
2021/02/06 Python
暇步士官网:Hush Puppies
2016/09/22 全球购物
表彰会主持词
2014/03/26 职场文书
爱国卫生月活动总结范文
2014/04/25 职场文书
教师反邪教心得体会
2016/01/15 职场文书
使用 Apache 反向代理的设置技巧
2022/01/18 Servers