当前位置: 首页 > news >正文

Python网络编程之FTP项目开发

目录

前言

项目演示

项目目录结构如下

项目菜单

上传文件功能

下载文件功能

ssh远程命令

项目结构讲解

服务端

EasyFileTran_se.py

run.py

功能文件

get_file.py

put_file.py

ssh.py

客户端

EasFileTran.py

main.py

ssh.py

结语

前言

博主在学习了一部分Python网络编程后熟悉了基于TCP协议的服务端与客户端之间的通信,于是从新手的角度独立开发了同时具有ssh远程命令以及ftp上传下载服务的项目-----EasyFileTran

此项目结构清晰明了,对新手挺友好的,博主已开源到github供各位新手小白当作入门学习的案例。

github地址:GitHub - jhli07/EasyFileTran: 一个python编写的简易文件传输,命令执行工具 · GitHub

项目演示

  • 项目目录结构如下

client

*download

EasyFileTran.py

get_file.py

main.py

put_file.py

ssh.py

server

*share

EasyFileTran_se.py

get_file.py

put_file.py

run.py

ssh.py

项目菜单

上传文件功能

设置完成服务端 端口后便可以成功连接

待上传文件目录地址为:\EasyFileTran\client\download\

(这是简化演示,服务端/客户端 上传下载目录均选在对应的同一个文件夹,后续可自行调整)

客户端输入:

put 12333.txt

可看到上传成功,服务端share目录中出现了此文件,可验证此功能成功

下载文件功能

输入命令

get 123.txt

同样可看到下载成功,再看客户端download文件夹中出现了此文件

ssh远程命令

此工具是在windows系统中演示,可输入常用的cmd命令

均可成功运行,至此项目的一些功能简单验证完,接下来进行项目结构的讲解

项目结构讲解

(此博客默认为有网络编程基础来开发项目,因此这部分主要拆解项目构建思路,并不会大范围讲述代码内容)

服务端

EasyFileTran_se.py

此文件为服务端的入口文件,负责启动服务端

from run import main if __name__ == '__main__': print('===================================') print('===================================') print('欢迎使用EasyFileTran FTP工具(服务端)') print('===================================') print('===================================') print('Author:Easy_Li') main()

可看到这个文件中包含主要的开始菜单页,从run.py中调用main函数

run.py

这个文件便为驱动服务端所有项目启动的主要文件,由EasyFileTran_se.py(入口文件)调用

内容如下

import socket import subprocess import json import struct from put_file import put_file from get_file import get_file from ssh import ssh def main(): port = int(input('输入你要开启的端口:')) server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('0.0.0.0',port)) server.listen(5) print('正在等待客户端连接......') while True: conn, client_addr = server.accept() print('客户端已连接!') while True: try: res = conn.recv(8096) if not res: break cmd = res.decode('utf-8').split() if(cmd[0]=='get'): put_file(conn,cmd) elif(cmd[0]=='put'): get_file(conn,cmd) else: ssh(conn, cmd) except ConnectionResetError: break conn.close() server.close()

此文件中包含创建socket接口,连接客户端等重要的功能,并处理来自于客户端不同的命令,每一个命令做出的不同相应又来自于其他文件

例如,cmd[0]=='get' ,也就是客户端输入get时,则调用服务端put_file.py文件中的put_file()函数,其他两种情况均相同,当输入命令不是我们规定的getput的时候,则默认启动ssh通道

下面我们来逐一分析

功能文件

get_file.py

这是客户端上传文件时,服务端对应执行的文件

import struct import json share_dir=r'D:\719web\Py_project\A_FTPSSH_tools\EasyFileTran\server\share' def get_file(conn,cmd): obj = conn.recv(4) header_size = struct.unpack('i', obj)[0] header_bytes = conn.recv(header_size) header_json = header_bytes.decode('utf-8') # 完整的json数据 header_dic = json.loads(header_json) total_size = header_dic['file_size'] filename = header_dic['filename'] with open('%s/%s' %(share_dir,filename), 'wb') as f: recv_size = 0 while (recv_size < total_size): line = conn.recv(1024) f.write(line) recv_size += len(line) print('总大小%s 已下载%s' % (total_size, recv_size))

在开头我们定义了服务端的待下载文件目录,后续优化,使其能够被用户自行定义

接着服务端接收传来的报头,对应解析报头,收取字典,解析字典,获取待下载文件的数据大小,最后进行下载文件,这里我们使用了一个解决粘包问题的简单算法

在while循环中,循环一次最多收取1024个 字节的数据,然后循环条件为累计收取数据小于文件总数据,最后保证成功下载整个文件,并在下载途中将实时下载进度显现出来

put_file.py

这是客户端下载文件时,服务端对应提供下载文时需要执行的文件

import os import json import struct share_dir=r'D:\719web\Py_project\A_FTPSSH_tools\EasyFileTran\server\share' def put_file(conn, cmd): try: filename = cmd[1] header_dic = { 'filename': filename, 'file_size': os.path.getsize(r'%s/%s' % (share_dir, filename)) } header_json = json.dumps(header_dic) header_bytes = header_json.encode('utf-8') conn.send(struct.pack('i', len(header_bytes))) conn.send(header_bytes) with open('%s/%s' % (share_dir, filename), 'rb') as f: for line in f: conn.send(line) except FileNotFoundError: print('系统找不到对应文件')

这是上传文件时构建一个字典,里面包含文件名,文件数据大小,然后将字典转化为json格式,再进行编码,打包制作报头,接着发送报头

随后发送文件,采取逐行的方式读取文件避免文件内容过大而卡爆内存,随后conn.send(line),逐行发送文件,届时我们可联想到客户端那边同样逐行接收文件然后逐行下载

ssh.py

此文件为处理客户端传来的windows/linux 的shell命令

import struct import subprocess def ssh(conn,cmd): cmds=cmd[0] obj = subprocess.Popen(cmds, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() totle=(len(stdout)+len(stderr)) conn.send(struct.pack('i',totle)) conn.send(stdout) conn.send(stderr)

接收命令,采用模拟打开shell环境的形式执行接收到的命令,并使用popen(管道)的形式存储命令执行结果,将执行成功和错误的两种结果分别存储至两个管道中

随后计算结果总大小,再进行打包,发送数据大小(报头),再发送数据结果

将两种结果的内容直接分两行发送,并未相加后再发送,这里是利用了粘包现象的特性,两种结果会自行合并,这里就实现了ssh远程命令执行的效果

客户端

由于服务端与客户端的上传/下载功能仅为反过来即可,因此这两个文件不做特别说明了

EasFileTran.py

此文件为客户端的入口文件,负责启动客户端

from main import main if __name__ == '__main__': print('============================') print('============================') print('欢迎使用EasyFileTran FTP工具') print('============================') print('============================') print('Author:Easy_Li') print('上传文件的命令格式为:put filename\n下载文件的命令格式为:get filename') main()

这里从main.py文件中调取main()函数进行运行客户端,因此我们可以推理到,客户端的main.py功能类似于服务端的run.py负责正式启动对应的服务

main.py

import socket import struct from get_file import get_file from put_file import put_file from ssh import get_ssh def main(): client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) obj_ip=input('请输入目标主机ip地址:') obj_port = int(input('请输入目标主机端口:')) client.connect((obj_ip,obj_port)) print('连接成功!') while True: cmd=input(obj_ip+":>> ").strip() if not cmd:continue client.send(cmd.encode('utf-8')) cmds = cmd.split() if(cmds[0]=='get'): get_file(client,cmds) elif(cmds[0]=='put'): put_file(client,cmds) else: get_ssh(client,cmds) client.close()

此文件实现功能为,获取用户输入的服务器ip地址以及端口,便可以与服务端进行通信,通过判断不同的输入命令,调用对应的功能文件

ssh.py

import struct def get_ssh(client,cmds): recv_sizessh=0 recv_data=b'' total = client.recv(4) total_sizessh=struct.unpack('i',total)[0] while (recv_sizessh < total_sizessh): line = client.recv(1024) recv_size=len(line) recv_sizessh += recv_size recv_data += line print(recv_data.decode('GBK'))

此文件为接收服务端 传来的shell命令执行结果,处理粘包问题的算法与接收文件时类似,这里使用recv_data += line将收到的数据逐个相加

注意windows中使用的是'GBK'编码,linux使用'utf-8'编码

结语

至此此项目全部文件都介绍完毕,供给各位做案例demo

思考:后续可不可以优化改进下,比如隐藏进程,做成钓鱼软件,我们就得到了一个自己开发的后门病毒,反弹shell工具,类似于中国菜刀,蚁剑这样的工具

http://www.jsqmd.com/news/931202/

相关文章:

  • 突破60帧束缚:Genshin_StarRail_fps_unlocker带你体验240Hz流畅游戏世界
  • 基于 YOLO11 + ByteTrack 的车辆检测跟踪与车流量统计系统实战
  • d2s-editor:暗黑破坏神2存档编辑终极指南,5分钟打造完美角色
  • 2026年6月国内比较好的树脂销售公司怎么选购,40寸滤芯 离子交换树脂/杜邦树脂/生活污水处理设备,树脂公司哪家权威 - 品牌推荐师
  • PPTist终极指南:免费在线PPT制作工具完全使用教程
  • 从零到一:全面解析加密货币交易所的开发与搭建
  • 相对绝对定位
  • 2026武汉收纳整理师推荐|武汉上门整理服务哪家靠谱?高口碑高性价比榜单 - 土星买买买
  • Trelby终极指南:为什么这款免费开源剧本写作软件能让创作者专注故事本身?
  • 打卡信奥刷题(3351)用C++实现信奥题 P9560 [SDCPC 2023] Math Problem
  • KNX智能照明避坑指南:用ETS5配置调光与场景时,90%新手会忽略的5个细节
  • 2024–2026视觉编码器十大变体技术梳理
  • YOLO11转CoreML完全指南:手把手教你如何将YOLO11转换为CoreML格式,并在iOS上测试。
  • 充电头暗藏玄机:宽幅变窄幅,低价背后是省钱还是埋雷?
  • 2026年5月目前靠谱的玉石厂商推荐,易加工石材/天然大理石/适配背景墙岩板/环保无异味岩板,玉石公司选哪家 - 品牌推荐师
  • 数字时代知识保存:从百科全书备份到长期存储技术实践
  • 3PEAK思瑞浦 TP5591-SR SOP8 精密运放
  • Java基础中级进阶篇二之IO流(IO流、嵌套类、多线程)
  • 反洗钱平台-互联网平台反洗钱系统全景设计
  • ncmdump:突破网易云音乐NCM加密的智能解密工具,5分钟解锁音乐自由
  • 长沙民办中职院校排行 5所合规办学机构实力解析 - 互联网科技品牌测评
  • 如何实现谷歌秒收录?让爬虫每天多抓500次的底层逻辑
  • 3步安装OmenSuperHub:终极免费的暗影精灵笔记本硬件管理工具
  • 南宋历代皇帝完整脉络全解析:偏安江南的百年抗争与崖山终章
  • 3步打造专业级无线网络安全测试:Fluxion钓鱼页面深度解析
  • MapStruct 与 Lombok 协作的注解处理器执行顺序分析
  • 公链革命2.0:Layer 1与Layer 2如何重构区块链开发者的黄金时代
  • m4s转MP4完整指南:3分钟解锁B站缓存视频的终极解决方案
  • MapLibre GL JS第36课:一个Source配置多个图层样式
  • 【收藏干货】2026 新版大模型转行全攻略:零基础小白、在职程序员转行避坑指南