实现终端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. SpringBoot第十四篇:统一异常处理

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10984081.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   本文将谈论 ...

  2. Beta冲刺(9/7)——2019.5.31

    作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Beta冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 队 ...

  3. PyQt5笔记之标签

    标签 QLabel用于显示文本或图像.没有提供用户交互功能.标签的视觉外观可以通过各种方式进行配置,并且可以用于为另一个窗口小部件指定焦点助记键. 一个QLabel可以包含以下任意内容类型: 内容 设 ...

  4. win10 配置IIS

    互联网信息服务(英語:Internet Information Services),在台湾被称为网际网路资讯服务,是由微软公司提供的基于运行Microsoft Windows的互联网基本服务.最初是W ...

  5. [Python学习笔记-007] 使用PyEnchant检查英文单词

    最近在教儿子做自然拼读,跟他玩了一个单词游戏,就是利用简单的枚举找出适合小朋友学习的两个字母的单词.人工找寻难免有疏漏之处,这里使用PyEnchant给出一个简单的脚本. 01 - foo.py #! ...

  6. vue单页面引入CDN链接

    不想在index.html文件中全局引入CDN资源,那么如何在Vue单文件组件中引入?下面来瞅瞅~ 虚拟DOM创建 Vue 通过创建一个虚拟 DOM 来追踪自己要改变的真实 DOM 什么是虚拟DOM? ...

  7. vue v-for 使用问题整理

    今天使用v-for指令的时候遇到一个错误 [Vue warn]: Error in render: "TypeError: Cannot read property 'children' o ...

  8. 【翻译】Tusdotnet中文文档(3)自定义功能和相关技术

    自定义功能和相关技术 本篇按照如下结构翻译 自定义功能 自定义数据仓库 相关技术 架构和总体概念 自定义数据仓库 tusdotnet附带一个存储库TusDiskStore,它将文件保存在磁盘上的一个目 ...

  9. 玩透二叉树(Binary-Tree)及前序(先序)、中序、后序【递归和非递归】遍历

    基础预热: 结点的度(Degree):结点的子树个数:树的度:树的所有结点中最大的度数:叶结点(Leaf):度为0的结点:父结点(Parent):有子树的结点是其子树的根节点的父结点:子结点/孩子结点 ...

  10. Linux 监控之 IO

    简单介绍下 Linux 中与 IO 相关的内容. 简介 可以通过如下命令查看与 IO 相关的系统信息. # tune2fs -l /dev/sda7 ← 读取superblock信息 # blockd ...