Python利用tcp_socket实现文件下载器
Python利用tcp_socket实现简单文件下载功能
文章目录
- Python利用tcp_socket实现简单文件下载功能
- 一、客户端
- 二、服务端
- 三、成果展示
- 3.1 创建测试文件
- 3.2 下载测试文件
- 3.3 查看下载文件
- 四、文件下载器升级版
- 4.1、更新公告
- 4.1.1 升级版客户端代码
- 4.1.2 升级版服务端代码
- 4.2 升级版成果展示
- 问题处理
一、客户端
客户端比较好写一点,我们先来实现客户端的功能
客户端实现原理:
- 创建tcp_socket, 通过IP地址与端口连接服务端
- 通过input函数获取filename并发送到服务端
- 接收到来自服务端发来的文件内容
- 判断发来的文件内容是否为空,如果为空,代表服务端发送异常,停止创建文件
- 如果不为空,创建新文件,写入服务端发来的内容
服务端发送的都是byte类型的数据,所以我们用wb方式写入文件
代码如下:
import os
import socketdef main():tcp_download_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)tcp_download_socket.connect((b'127.0.0.1',7788))while True:file_name=input('请输入要下载的文件内容')tcp_download_socket.send(file_name.encode('utf-8')) #发送filenamerecv_data=tcp_download_socket.recv(1024*1024) #最大限制1MBprint('开始写入文件---')if recv_data:with open('new_'+ file_name,'bw') as doenload_file:doenload_file.write(recv_data)doenload_file.close()if os.path.isfile('new_'+ file_name):print('下载文件成功')answer = input("是否下载其他文件")if answer == 'y' or answer == 'Y':continueelse:breakelse:print("服务端不存在该文件,请检查后重试")continueif __name__ == '__main__':main()
二、服务端
客户端没问题了,我们实现一下服务端
服务端实现原理:
- 创建服务端socket,并绑定7788端口
- 开始持续监听7788端口,此时阻塞
- 客户端发送连接请求,连接客户端成功,服务端解阻塞
- 接收到客户端发送的filename,调用os模块判断文件是否存在
- 若存在,使用with以rb方式查看文件,并赋值data=file.read(),向客户端发送data
- 若不存在文件,不返回任何内容,此时服务端也会做出相应动作
服务端代码如下:
import socket
import osdef main():server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server_socket.bind(('',7788))server_socket.listen(128) #最多允许128个客户端同时连接while True:print("===开始接收请求===")new_server_socket,client_addr=server_socket.accept()print(f'客户端已建立连接,客户端地址是{client_addr}')while True:if new_server_socket:file_name=new_server_socket.recv(1024) #接收filenameif os.path.isfile(file_name):with open(file_name,'rb') as file:data=file.read()new_server_socket.send(data)else:print("文件不存在")new_server_socket.close()breakelse:print("客户端关闭连接")breakif __name__ == "__main__" :main()
三、成果展示
为了方便,我们用pycharm来演示
3.1 创建测试文件
aaa.txt
3.2 下载测试文件
客户端操作如下:
服务端响应如下:
3.3 查看下载文件
四、文件下载器升级版
之前的文件下载虽然实现了下载的功能,但是如果是陌生的服务器,我们并不知道对方服务器的文件到底有哪些,于是我就升级了一下程序
4.1、更新公告
- 服务端会首先向客户端发送程序所在目录的文件列表,以供客户端下载
- 使用logging模块,打印标准日志,更易观察
- 修复已知BUG
代码如下:
4.1.1 升级版客户端代码
import ast
import logging
import os
import socket
from prettytable import PrettyTableu = PrettyTable(['文件名', '文件大小'])Format = logging.Formatter('%(levelname)s %(asctime)s %(filename)s %(funcName)s %(message)s ')
logger = logging.getLogger()
logger.setLevel('DEBUG')
console_handle = logging.StreamHandler()
console_handle.setLevel(level='INFO')
console_handle.setFormatter(Format)
logger.addHandler(console_handle)def get_file_info():tcp_download_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)tcp_download_socket.connect((b'127.0.0.1', 7789))tcp_download_socket.send('getfile'.encode('utf-8'))filelist = tcp_download_socket.recv(1024)# 使用ast模块的literal_eval,将str转换为dictfile_info = ast.literal_eval(filelist.decode('utf-8'))# 通过for循环与preaytable模块,创建表格for key, value in file_info.items():u.add_row([key, str(value)])print(u)tcp_download_socket.close()def main():print('目标服务器文件列表如下')get_file_info()while True:tcp_download_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)tcp_download_socket.connect((b'127.0.0.1', 7788))print('\n')file_name = input('请输入要下载的文件内容:')tcp_download_socket.send(file_name.encode('utf-8')) # 发送filenamerecv_data = tcp_download_socket.recv(1024 * 1024) # 最大限制1MBlogger.info('开始写入文件---')if recv_data:if recv_data.decode('utf-8') == 'filenotexists':logger.error('file not exists')tcp_download_socket.close()continueelse:with open('new_' + file_name, 'bw') as doenload_file:doenload_file.write(recv_data)doenload_file.close()if os.path.isfile('new_' + file_name):logger.info('下载文件成功')tcp_download_socket.close()answer = input("是否下载其他文件")if answer == 'y' or answer == 'Y':continueelse:breakif __name__ == '__main__':main()
4.1.2 升级版服务端代码
import socket
import os
import logging
import threadingFormat = logging.Formatter('%(levelname)s %(asctime)s %(filename)s %(funcName)s %(message)s ')
logger = logging.getLogger()
logger.setLevel('DEBUG')
console_handle = logging.StreamHandler()
console_handle.setLevel(level='INFO')
console_handle.setFormatter(Format)
logger.addHandler(console_handle)def send_file_info():while True:logger.info("===开始接收发送信息请求===")file_info = {}files = os.listdir('.')for file in files:# 获取文件大小,因为文件太小多以取两位小数file_size = round(os.path.getsize(file) / 1024, 3)file_info[file] = f'{file_size}kb'tcp_getlist_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 为避免端口冲突,使用其他端口tcp_getlist_socket.bind(('', 7789))tcp_getlist_socket.listen(128)logger.info('创建发送文件信息套接字')new_server_socket, client_addr = tcp_getlist_socket.accept()logger.info(f'接收信息客户端已建立连接,客户端地址是{client_addr}')new_server_socket.send(str(file_info).encode('utf-8'))logger.info('成功发送客户端信息')# new_server_socket.close()# tcp_getlist_socket.close()logger.info('关闭发送文件信息套接字')def main():# 创建send_file线程t1 = threading.Thread(target=send_file_info)t1.start()server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.bind(('', 7788))server_socket.listen(128) # 最多允许128个客户端同时连接while True:logger.info("===开始接收下载请求===")new_server_socket, client_addr = server_socket.accept()logger.info(f'下载客户端已建立连接,客户端地址是{client_addr}')while True:if new_server_socket:file_name = new_server_socket.recv(1024).decode('utf-8') # 接收filenameif os.path.isfile(file_name):with open(file_name, 'rb') as file:data = file.read()logger.info('发送文件{0}内容'.format(file_name))new_server_socket.send(data)new_server_socket.close()breakelse:logger.error("文件不存在")new_server_socket.send('filenotexists'.encode('utf8'))new_server_socket.close()breakelse:print("客户端关闭连接")breakif __name__ == "__main__":main()
4.2 升级版成果展示
服务端启动服务开始监听
客户端启动:
首先会打印服务端文件内容,以列表形式展示
输入下载文件名 aaa.txt
成功下载
服务端日志如下:
很明显看到我是建立了两次链接的,前一次是为了接受文件列表信息
当文件不存在时,服务端会发送 file not exists 消息,客户端收到消息后,做出相应动作
重新填写正确文件,下载成功
问题处理
1、发送文件函数只发送一次,当客户端第二次启动时,会报连接失败
原因:发送文件函数只调用一次,第二次客户端连接时,函数socket实际上已关闭
解决方法:
给函数加上while True,去掉close方法,创建多线程
# 创建send_file线程t1 = threading.Thread(target=send_file_info)t1.start()
Python利用tcp_socket实现文件下载器相关推荐
- python文件下载器代码_GitHub - applechi/pythonCollection: python代码集合(文件下载器、pdf合并、极客时间专栏下载、掘金小册下载、新浪微博爬虫等)...
json2mysql 这次更新了将一个json文件中的数据导入到mysql的脚本. 是用nodejs写的. 对应的文件是tomysql.js 有兴趣的同志可以研究下. pythonCollection ...
- python写一个文件下载器_Python3使用TCP编写一个简易的文件下载器
原标题:Python3使用TCP编写一个简易的文件下载器 利用Python3来实现TCP协议,和UDP类似.UDP应用于及时通信,而TCP协议用来传送文件.命令等操作,因为这些数据不允许丢失,否则会造 ...
- python类加载器_利用Python反序列化运行加载器实现免杀
前言 前几天在看Python的shellcode加载器,在网上找了一个,结果加载器自身就过不了火绒,测试发现是火绒对关键语句进行了识别. 所以我们要想办法去掉加载器中明显的特征. 原理及实现 在绕过静 ...
- TCP文件下载器(Python)
使用TCP编写一个文件下载器,分为客户端和服务器,此博客为上一篇的延伸,增加了文件读写编程. 下载器服务器程序: import socketdef send_file_client(new_clien ...
- php5.5 反序列化利用工具_利用Python反序列化运行加载器实现免杀
前言 前几天在看Python的shellcode加载器,在网上找了一个,结果加载器自身就过不了火绒,测试发现是火绒对关键语句进行了识别. 所以我们要想办法去掉加载器中明显的特征. 原理及实现 在绕过静 ...
- python写一个文件下载器_python使用tcp实现一个简单的下载器
上一篇中介绍了tcp的流程,本篇通过写一个简单的文件下载器程序来巩固之前学的知识. 文件下载器的流程如下: 客户端: 输入目标服务器的ip和port 输入要下载文件的名称 从服务器下载文件保存到本地 ...
- python高级 笔记 08 (TCP服务器增强 + 文件下载器 案例 综合应用)
TCP服务器接受客户端多条信息 主要方式: 通过在接受信息,等待数据 recv前增加一个死循环 import sockettcp_client_socket = socket.socket(socke ...
- 网络 #TCP #UDP #文件下载器 #网络通信
网络 网络基础 1)IP地址 1>查看网卡信息 2>IP地址分类 3>私有IP 2)端口 1>端口的分类(部分) 1.知名端口 2.动态端口 2>查看端口号 3)sock ...
- python多进程断点续传分片下载器
python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...
最新文章
- php跳过当前后续代码,PHP用continue跳过本次循环中剩余代码的注意点
- 810D - 如何写学术论文
- Oracle 登录时错误: ORA-01017: invalid username/password; logon denied
- Java MySql 连接数据库
- LAMP介绍,Apache安装细节过程
- Lync-技巧-2.启用-用户-启用-语音-设置-线路URI
- 【转】删除已经存在的 TFS Workspace
- oracle数据泵导入很慢,impdp导入效率的问题
- CSS实现垂直居中布局
- C# Attribute(中)——Attribute本质论
- java根据系统时间拼凑文件名字
- ros melodic控制真实机械臂之openmanipulator参考
- css制作tips提示框,气泡框,制作三角形
- 计划任务,机器码与注册码,Web服务
- valgrind 报告 ecpg内存泄露 (二)
- android4.4 adb工具包,Android ADB工具
- 使用 Chrome 浏览器截取网页长图
- 安装pyHive报错
- 播放音乐的html代码,音乐播放器-html代码
- 漫反射贴图与镜面光贴图