目录前言项目演示项目目录结构如下项目菜单上传文件功能下载文件功能ssh远程命令项目结构讲解服务端EasyFileTran_se.pyrun.py功能文件get_file.pyput_file.pyssh.py客户端EasFileTran.pymain.pyssh.py结语前言博主在学习了一部分Python网络编程后熟悉了基于TCP协议的服务端与客户端之间的通信于是从新手的角度独立开发了同时具有ssh远程命令以及ftp上传下载服务的项目-----EasyFileTran此项目结构清晰明了对新手挺友好的博主已开源到github供各位新手小白当作入门学习的案例。github地址GitHub - jhli07/EasyFileTran: 一个python编写的简易文件传输命令执行工具 · GitHub项目演示项目目录结构如下client*downloadEasyFileTran.pyget_file.pymain.pyput_file.pyssh.pyserver*shareEasyFileTran_se.pyget_file.pyput_file.pyrun.pyssh.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(输入你要开启的端口)) serversocket.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()函数其他两种情况均相同当输入命令不是我们规定的get或put的时候则默认启动ssh通道下面我们来逐一分析功能文件get_file.py这是客户端上传文件时服务端对应执行的文件import struct import json share_dirrD:\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_dirrD:\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): cmdscmd[0] obj subprocess.Popen(cmds, shellTrue, stdoutsubprocess.PIPE, stderrsubprocess.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.pyimport 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_ipinput(请输入目标主机ip地址) obj_port int(input(请输入目标主机端口)) client.connect((obj_ip,obj_port)) print(连接成功!) while True: cmdinput(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.pyimport struct def get_ssh(client,cmds): recv_sizessh0 recv_datab total client.recv(4) total_sizesshstruct.unpack(i,total)[0] while (recv_sizessh total_sizessh): line client.recv(1024) recv_sizelen(line) recv_sizessh recv_size recv_data line print(recv_data.decode(GBK))此文件为接收服务端 传来的shell命令执行结果处理粘包问题的算法与接收文件时类似这里使用recv_data line将收到的数据逐个相加注意windows中使用的是GBK编码linux使用utf-8编码结语至此此项目全部文件都介绍完毕供给各位做案例demo思考后续可不可以优化改进下比如隐藏进程做成钓鱼软件我们就得到了一个自己开发的后门病毒反弹shell工具类似于中国菜刀蚁剑这样的工具
Python网络编程之FTP项目开发
目录前言项目演示项目目录结构如下项目菜单上传文件功能下载文件功能ssh远程命令项目结构讲解服务端EasyFileTran_se.pyrun.py功能文件get_file.pyput_file.pyssh.py客户端EasFileTran.pymain.pyssh.py结语前言博主在学习了一部分Python网络编程后熟悉了基于TCP协议的服务端与客户端之间的通信于是从新手的角度独立开发了同时具有ssh远程命令以及ftp上传下载服务的项目-----EasyFileTran此项目结构清晰明了对新手挺友好的博主已开源到github供各位新手小白当作入门学习的案例。github地址GitHub - jhli07/EasyFileTran: 一个python编写的简易文件传输命令执行工具 · GitHub项目演示项目目录结构如下client*downloadEasyFileTran.pyget_file.pymain.pyput_file.pyssh.pyserver*shareEasyFileTran_se.pyget_file.pyput_file.pyrun.pyssh.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(输入你要开启的端口)) serversocket.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()函数其他两种情况均相同当输入命令不是我们规定的get或put的时候则默认启动ssh通道下面我们来逐一分析功能文件get_file.py这是客户端上传文件时服务端对应执行的文件import struct import json share_dirrD:\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_dirrD:\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): cmdscmd[0] obj subprocess.Popen(cmds, shellTrue, stdoutsubprocess.PIPE, stderrsubprocess.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.pyimport 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_ipinput(请输入目标主机ip地址) obj_port int(input(请输入目标主机端口)) client.connect((obj_ip,obj_port)) print(连接成功!) while True: cmdinput(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.pyimport struct def get_ssh(client,cmds): recv_sizessh0 recv_datab total client.recv(4) total_sizesshstruct.unpack(i,total)[0] while (recv_sizessh total_sizessh): line client.recv(1024) recv_sizelen(line) recv_sizessh recv_size recv_data line print(recv_data.decode(GBK))此文件为接收服务端 传来的shell命令执行结果处理粘包问题的算法与接收文件时类似这里使用recv_data line将收到的数据逐个相加注意windows中使用的是GBK编码linux使用utf-8编码结语至此此项目全部文件都介绍完毕供给各位做案例demo思考后续可不可以优化改进下比如隐藏进程做成钓鱼软件我们就得到了一个自己开发的后门病毒反弹shell工具类似于中国菜刀蚁剑这样的工具