Python实现的FTP通信客户端与服务器端功能示例
作者:chengqiuming 发布时间:2023-10-02 21:36:01
标签:Python,FTP通信,客户端,服务器端
本文实例讲述了Python实现的FTP通信客户端与服务器端功能。分享给大家供大家参考,具体如下:
一 代码
1、服务端代码
import socket
import threading
import os
import struct
#用户账号、密码、主目录
#也可以把这些信息存放到数据库中
users = {'zhangsan':{'pwd':'zhangsan1234', 'home':r'c:\python 3.5'},
'lisi':{'pwd':'lisi567', 'home':'c:\\'}}
def server(conn,addr, home):
print('新客户端:'+str(addr))
#进入当前用户主目录
os.chdir(home)
while True:
data = conn.recv(100).decode().lower()
#显示客户端输入的每一条命令
print(data)
#客户端退出
if data in ('quit', 'q'):
break
#查看当前文件夹的文件列表
elif data in ('list', 'ls', 'dir'):
files = str(os.listdir(os.getcwd()))
files = files.encode()
conn.send(struct.pack('I', len(files)))
conn.send(files)
#切换至上一级目录
elif ''.join(data.split()) == 'cd..':
cwd = os.getcwd()
newCwd = cwd[:cwd.rindex('\\')]
#考虑根目录的情况
if newCwd[-1] == ':':
newCwd += '\\'
#限定用户主目录
if newCwd.lower().startswith(home):
os.chdir(newCwd)
conn.send(b'ok')
else:
conn.send(b'error')
#查看当前目录
elif data in ('cwd', 'cd'):
conn.send(str(os.getcwd()).encode())
elif data.startswith('cd '):
#指定最大分隔次数,考虑目标文件夹带有空格的情况
#只允许使用相对路径进行跳转
data = data.split(maxsplit=1)
if len(data) == 2 and os.path.isdir(data[1]) \
and data[1]!=os.path.abspath(data[1]):
os.chdir(data[1])
conn.send(b'ok')
else:
conn.send(b'error')
#下载文件
elif data.startswith('get '):
data = data.split(maxsplit=1)
#检查文件是否存在
if len(data) == 2 and os.path.isfile(data[1]):
conn.send(b'ok')
fp = open(data[1], 'rb')
while True:
content = fp.read(4096)
#发送文件结束
if not content:
conn.send(b'overxxxx')
break
#发送文件内容
conn.send(content)
if conn.recv(10) == b'ok':
continue
fp.close()
else:
conn.send(b'no')
#无效命令
else:
pass
conn.close()
print(str(addr)+'关闭连接')
#创建Socket,监听本地端口,等待客户端连接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 10600))
sock.listen(5)
while True:
conn, addr = sock.accept()
#验证客户端输入的用户名和密码是否正确
userId, userPwd = conn.recv(1024).decode().split(',')
if userId in users and users[userId]['pwd'] == userPwd:
conn.send(b'ok')
#为每个客户端连接创建并启动一个线程,参数为连接、客户端地址、客户主目录
home = users[userId]['home']
t = threading.Thread(target=server, args=(conn,addr,home))
t.daemon = True
t.start()
else:
conn.send(b'error')
2、客户端代码
import socket
import sys
import re
import struct
import getpass
def main(serverIP):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((serverIP, 10600))
userId = input('请输入用户名:')
#使用getpass模块的getpass()方法获取密码,不回显
userPwd = getpass.getpass('请输入密码:')
message = userId+','+userPwd
sock.send(message.encode())
login = sock.recv(100)
#验证是否登录成功
if login == b'error':
print('用户名或密码错误')
return
#整数编码大小
intSize = struct.calcsize('I')
while True:
#接收客户端命令,其中##>是提示符
command = input('##> ').lower().strip()
#没有输入任何有效字符,提前进入下一次循环,等待用户继续输入
if not command:
continue
#向服务端发送命令
command = ' '.join(command.split())
sock.send(command.encode())
#退出
if command in ('quit', 'q'):
break
#查看文件列表
elif command in ('list', 'ls', 'dir'):
loc_size = struct.unpack('I', sock.recv(intSize))[0]
files = eval(sock.recv(loc_size).decode())
for item in files:
print(item)
#切换至上一级目录
elif ''.join(command.split()) == 'cd..':
print(sock.recv(100).decode())
#查看当前工作目录
elif command in ('cwd', 'cd'):
print(sock.recv(1024).decode())
#切换至子文件夹
elif command.startswith('cd '):
print(sock.recv(100).decode())
#从服务器下载文件
elif command.startswith('get '):
isFileExist = sock.recv(20)
#文件不存在
if isFileExist != b'ok':
print('error')
#文件存在,开始下载
else:
print('downloading.', end='')
fp = open(command.split()[1], 'wb')
while True:
print('.', end='')
data = sock.recv(4096)
if data == b'overxxxx':
break
fp.write(data)
sock.send(b'ok')
fp.close()
print('ok')
#无效命令
else:
print('无效命令')
sock.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Usage:{0} serverIPAddress'.format(sys.argv[0]))
exit()
serverIP = sys.argv[1]
if re.match(r'^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$', serverIP):
main(serverIP)
else:
print('服务器地址不合法')
exit()
二 运行结果
客户端运行结果
希望本文所述对大家Python程序设计有所帮助。
来源:https://blog.csdn.net/chengqiuming/article/details/78601165
0
投稿
猜你喜欢
- #!/usr/local/bin/php -q author:freemouse <?php // 下面是说明. print (&qu
- 本文实例讲述了js控制多图左右滚动切换效果。分享给大家供大家参考。具体如下:这是一款纯js实现点击左右按钮图片自动左右平滑滚动,默认5个一组
- HTTP-REFERER这个变量已经越来越不可靠了,完全就是可以伪造出来的东东。 以下是伪造方法:ASP/Visual Basic代码 di
- 本文实例为大家分享了PyQt5实现暗黑风格的计时器的具体代码,供大家参考,具体内容如下主要是学习多线程知识,使用的是QTime(),但是似乎
- 问:怎样解决MySQL 5.0.16的乱码问题?答:MySQL 5.0.16的乱码问题可以用下面的方法解决:1.设置phpMyAdminLa
- Firefox 3.5已经发布了几个月了,且已经历5次小幅更新。而基于Gecko 1.9.2的Firefox 3.6也已经开发数月,现在已经
- gchart:基于google图表API的jquery组件全攻略——入门gchart是基于google图表API的jquery组件。使用gc
- 在oracle中有很多关于日期的函数,如:1、add_months()用于从一个日期值增加或减少一些月份 date_value:=add_m
- 前阵子刚完成一个B/S架构的学校办公系统,体会就是表太多,文件太多,而每个文件中类似的操作(代码)也太多了,例如学生信息和教师信息操作,st
- 图形由json格式加载,可以灵活配置。下一步是完善用户的操作,做这个感觉还是蛮有意思的。呵呵。截图:部分源码:<script type
- 这章是结合之前学习的Tensforboard与Transforms的一个练习。直接上代码:from PIL import Imagefrom
- 最近,在搞这个东西,网上也找不到asp相关的,如果有人很早弄出来了,也不要笑话偶;费了好久,总算搞定;原理:用stream对象预读文件的头两
- 生活中,我们在登录微博,邮箱的时候,常常会碰到验证码。在工作时,如果想要爬取一些数据,也会碰到验证码的阻碍。本次试验将带领大家认识验证码的一
- 一、is_numberic函数简介国内一部分CMS程序里面有用到过is_numberic函数,我们先看看这个函数的结构bool is_num
- 很多互联网应用程序都提供了全文搜索功能,用户可以使用一个词或者词语片断作为查询项目来定位匹配的记录。在后台,这些程序使用在一个SELECT查
- 通过亲密性原则,我们可以将一个页面中的元素按照某种逻辑理解上的差异划分成不同的元素组合;再通过对齐原则,使这些不同的元素组合在视觉上看起来彼
- 最近项目中需要Python的打包,看到网上也没有很详细的资料,于是做了一些示例程序。研究了一下,Python如何在Windows和Linux
- 在刚过去不久的6月30日那天,国外一位在YouTube拥有上千万粉丝的我的世界游戏主播Technoblade因癌症与世长辞,年仅23岁,他并
- 只有mdf文件的数据库附加失败的修复 附加时报如下错误: 服务器: 消息 1813,级别 16,状态 2,行 1 未能打开新数据库 '
- 解决办法: 1.新建一个同名的数据库(数据文件与原来的要一致) 2.再停掉sql server(注意不要分离数据库) 3.用原数据库的数据文