python

超轻量级php框架startmvc

Python实现的FTP通信客户端与服务器端功能示例

更新时间:2020-05-25 19:42:01 作者:startmvc
本文实例讲述了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 FTP通信 客户端 服务器端