实现终端FTP文件传输

代码结构:

.
├── client.py
├── readme.txt
└── server.py

运行截图:

readme.txt

tftp文件服务器

项目功能:
* 客户端有简单的页面命令提示
* 功能包含:
1、查看服务器文件库中的文件列表(普通文件) -> os.listdir
2、可以下载其中的某个文件到本地
3、可以上传客户端文件到服务器文件库
* 服务器需求:
1、允许多个客户端同时操作
2、每个客户端可能会连续发送命令 技术分析:
1、TCP套接字更适合文件传输
2、并发方案 -> fork多进程并发
3、对文件的读写操作
4、获取文件列表 -> os.listdir() 或 tree
5、粘包的处理 整体结构设计:
1、服务器功能封装在类中(上传,下载,查看列表)
2、创建套接字,流程函数调用main()
3、客户端负责发起请求,接收回复,展示
4、服务端负责接受请求,逻辑处理 编程实现:
1、搭建整体结构,创建网络连接
2、创建多进程和类的结构
3、每个功能模块的实现 模块方法:
os.listdir(path)
os.path.isfile()
os.path.isdir()

server.py

# server.py

import struct
from socket import *
import os
import signal
import sys
import time # 文件库
FILE_PATH = '/home/noon/Python/Example/' # 实现功能模块
class TftpServer(object):
def __init__(self, sockfd, addr):
super().__init__()
self.sockfd = sockfd
self.addr = addr
self.opt = '' def display(self):
re = ''
for i in os.listdir(FILE_PATH):
re += i + '\n'
self.sockfd.send(re.encode()) def download(self):
'下载模块功能实现'
# 尝试打开文件
filename = FILE_PATH + self.opt.split(' ')[1]
print(filename)
try:
fp = open(filename, 'rb')
except:
self.sockfd.send(b'Failed to open file')
else:
self.sockfd.send(b'Ready to transfer')
# 循环发送数据
while True:
data = fp.read(1024)
if not data:
# 如果传输完毕,data为空,传输0,跳出循环
res = struct.pack('i', 0)
self.sockfd.send(res)
break
res = struct.pack('i', len(data))
self.sockfd.send(res)
self.sockfd.send(data)
print('Done!') def upload(self):
filename = FILE_PATH + self.opt.split(' ')[1]
try:
fp = open(filename, 'wb')
except:
self.sockfd.send('Unable to open file'.encode())
else:
self.sockfd.send(b'Ready to upload')
while True:
res = self.sockfd.recv(4)
length = struct.unpack('i', res)[0]
if length == 0:
break
data = self.sockfd.recv(length)
fp.write(data)
fp.close()
print('Done!') def quit(self):
print(self.addr, '断开连接')
self.sockfd.close()
sys.exit() # 主流程
def main():
HOST = '0.0.0.0'
PORT = 5555
ADDR = (HOST, PORT) sockfd = socket()
sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sockfd.bind(ADDR)
sockfd.listen(5) # 通知内核对子进程的结束不关心,由内核回收。
signal.signal(signal.SIGCHLD, signal.SIG_IGN) while True:
try:
connfd, addr = sockfd.accept()
except KeyboardInterrupt:
sockfd.close()
sys.exit('服务器退出')
except Exception as e:
print(e)
continue print('连接成功:', addr) # 创建子进程
pid = os.fork() if pid == 0:
sockfd.close()
tftp = TftpServer(connfd, addr)
while True:
tftp.opt = connfd.recv(1024).decode()
if tftp.opt == 'display':
tftp.display()
elif tftp.opt.startswith('download'):
tftp.download()
elif tftp.opt.startswith('upload'):
tftp.upload()
elif tftp.opt == 'quit':
tftp.quit()
else:
connfd.close()
continue if __name__ == '__main__':
main()

client.py

# client.py

from socket import *
import sys
import time
import struct # 实现各种功能请求
class TftpClient(object):
def __init__(self, sockfd):
super().__init__()
self.sockfd = sockfd
self.opt = '' def panel(self):
print('+', '*'*30, '+', sep='')
print('+', 'display'.center(30), '+', sep='')
print('+', 'download'.center(30), '+', sep='')
print('+', 'upload'.center(30), '+', sep='')
print('+', 'quit'.center(30), '+', sep='')
print('+', '*'*30, '+', sep='') def display(self):
self.sockfd.send(b'display')
print(self.sockfd.recv(1024).decode()) def download(self):
'客户端下载请求'
# 先使用display命令向服务器请求文件列表,验证用户想要下载的文件是否存在
filename = input('filename>> ')
if not filename:
return
self.sockfd.send(b'display')
files = self.sockfd.recv(1024).decode().split('\n')
if not filename in files:
print('Cannot locate', filename)
return
# 文件存在,发送下载请求到服务端,并接收返回结果
data = 'download ' + filename
self.sockfd.send(data.encode())
data = self.sockfd.recv(1024).decode()
# 如果服务端无法打开文件
if data == 'Failed to open file':
print('Failed to open file')
# 可以执行下载操作
else:
# 调用写方法
print(data)
self.write(filename)
print('Done!') def write(self, filename):
'从服务器下载文件'
# 考虑到粘包问题,导入struct模块,接收服务端要发送的数据的大小,再按照这个大小接收数据,循环执行
fp = open(filename, 'wb')
while True:
# 接收数据大小,调用struct.unpack方法获得数据大小
res = self.sockfd.recv(4)
length = struct.unpack('i', res)[0]
# 如果数据大小为0,说明传输结束,退出循环
if length == 0:
break
# 按照数据的大小接收数据
data = self.sockfd.recv(length)
fp.write(data)
fp.close() def upload(self):
# 文件路径
filepath = input('filepath>> ')
try:
fp = open(filepath, 'rb')
except:
print('Unable to open', filepath)
return
else:
# 文件上传要保存为什么名字
# 先使用display命令向服务器请求文件列表,验证用户想要上传的文件名是否存在
filename = input('filename>> ')
if not filename:
return
self.sockfd.send(b'display')
files = self.sockfd.recv(1024).decode().split('\n')
if filename in files:
print('File already exists!')
return
# 可以上传
data = 'upload ' + filename
self.sockfd.send(data.encode())
data = self.sockfd.recv(1024).decode()
if data == 'Unable to open file':
print('服务器打开文件出错')
return
else:
self.read(fp) def read(self, fp):
'读取文件上传服务器'
while True:
data = fp.read(1024)
if not data:
res = struct.pack('i', 0)
self.sockfd.send(res)
break
res = struct.pack('i', len(data))
self.sockfd.send(res)
self.sockfd.send(data)
print('Done!') def quit(self):
self.sockfd.send(b'quit')
self.sockfd.close()
sys.exit('客户端关闭') # 创建套接字,建立连接
def main():
argc = len(sys.argv)
if argc != 3:
sys.exit('Usage: python client.py host port')
else:
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = HOST, PORT sockfd = socket()
try:
sockfd.connect(ADDR)
except ConnectionRefusedError:
sys.exit('无法连接到服务端') tftp = TftpClient(sockfd) tftp.panel()
while True:
try:
tftp.opt = input('>> ').lower()
except KeyboardInterrupt:
tftp.quit()
if tftp.opt == 'display':
tftp.display()
elif tftp.opt == 'download':
tftp.download()
elif tftp.opt == 'upload':
tftp.upload()
elif tftp.opt == 'quit':
tftp.quit()
else:
continue if __name__ == '__main__':
main()

Python实现终端FTP文件传输的更多相关文章

  1. FTP 文件传输服务

    昨晚心血来潮,尝试用python写了一个ftp文件传输服务,可以接收指令,从远程ftp服务器同步指定目录数据,最后没用上,开源出来. https://github.com/jadepeng/ftp_t ...

  2. 【RL-TCPnet网络教程】第35章 FTP文件传输协议基础知识

    第35章      FTP文件传输协议基础知识 本章节为大家讲解FTP(File Transfer Protocol,文件传输协议)的基础知识,方便后面章节的实战操作. (本章的知识点主要整理自网络) ...

  3. FTP文件传输服务

    FTP文件传输服务 一 .FTP 连接及传输的模式 l  控制连接:TCP21,用于发送FTP命令信息. l  数据连接:TCP 20, 用于上传下载数据. · 数据连接建立的类型: ·主动模式: 服 ...

  4. SSIS 学习之旅 FTP文件传输-脚本任务

    这一章主要讲解一下用脚本怎么把CSV文件抛送到FTP服务器上 设计:   通过Demon库的Users表数据生成CSV文件.   生成后的CSV文件抛送到FTP指定目录下. 控件的使用这里就不做详细讲 ...

  5. linux之FTP服务搭建 ( ftp文件传输协议 VSFTPd虚拟用户)

    FTP服务搭建 配置实验之前关闭防火墙 iptables -F iptables -X iptables -Z systemctl stop firewalld setenforce 0 1.ftp简 ...

  6. FTP文件传输

    FTP项目作业要求:1.用户加密认证2.允许同时多用户登录3.每个用户有自己的家目录,且只能访问自己的家目录4.对用户进行磁盘配额,每个用户的可用空间不同5.允许用户在ftp server上随意切换目 ...

  7. FTP(文件传输协议)工作原理

    目前在网络上,如果你想把文件和其他人共享.最方便的办法莫过于将文件放FTP服务器上,然后其他人通过FTP客户端程序来下载所需要的文件. 1.FTP架构 如同其他的很多通讯协议,FTP通讯协议也采用客户 ...

  8. FTP文件传输协议两种模式 ftp协议集,错误码集,ftp客户端命令集

    TCP/IP协议中,FTP标准命令TCP端口号为21,Port方式数据端口为20.FTP协议的任务是从一台计算机将文件传送到另一台计算机,它与这两台计算机所处的位置.联接的方式.甚至是是否使用相同的操 ...

  9. Linux菜鸟成长日记 ( Linux 下的 ftp 文件传输协议 )

    https://blog.csdn.net/buster_zr/article/details/80244542 FTP FTP 是 File Transfer Protocol (文件传输协议)的英 ...

随机推荐

  1. Econ 493 A1 - Fall 2019

    Econ 493 A1 - Fall 2019Homework 4Assignment InformationThis assignment is due on Monday November 18 ...

  2. Java8 新特性 Stream 短路终端操作

    短路终端操作 Java8 新特性 Stream 练习实例 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 none ...

  3. struts2被淘汰的原因

    Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个Servlet.在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互.Struts2 ...

  4. 提高性能,MySQL 读写分离环境搭建(一)

    这是松哥之前一个零散的笔记,整理出来分享给大伙! MySQL 读写分离在互联网项目中应该算是一个非常常见的需求了.受困于 Linux 和 MySQL 版本问题,很多人经常会搭建失败,今天松哥就给大伙举 ...

  5. Jenkins生成APK链接的二维码

    Window环境 1.下载安装Python如3.7.5版本,安装Python到电脑上如C:\Python37,将C:\Python37,C:\Python37\Scripts添加到Path环境变量中 ...

  6. uni-app如何解决在for循环里调用异步请求获取数据顺序混乱问题?

    总结/朱季谦 先前有一次做uni-app的js接口对接时,遇到过这样的情况,在for循环里,调用一个异步请求时,返回来的值顺序是乱的,因此,在以下的代码里,push到数组里的值,每次的顺序可能都是不一 ...

  7. 线程之间灵活传递信号(ManualResetEventSlim )

    当主程序启动时,首先创建ManualResetEventSlim 类的一个实例.然后启动三个线程,等待事件信号通知它们继续执行. /// <summary> /// 创建 ManualRe ...

  8. 图层树右键菜单结合Command操作过程

         图层树右键菜单结合Command操作过程 根据老师线上培训图层树右键菜单的生成,添加contextMenuStrip后再依次添加.命名ToolStripMenuItem,若将全部‘项’添加C ...

  9. salesforce零基础学习(九十四)classic下pagelayout引入的vf page弹出内容更新此page layout

    我们在classic环境中,有时针对page layout不能实现的地方,可以引入 一个vf page去增强标准的 page layout 功能,有时可能要求这个 vf page的部分修改需要更新此 ...

  10. git远程写协作同步

    1:创建一个要提交的文件2 git init 初始化 3 git remote add origin https://github.com/maohongli/cang.git 建立远程连接4 git ...