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


Posted in Python onMarch 28, 2018

本文实例讲述了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通信客户端与服务器端功能示例

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
使用python绘制人人网好友关系图示例
Apr 01 Python
python实现rest请求api示例
Apr 22 Python
python实现的守护进程(Daemon)用法实例
Jun 02 Python
python 如何快速找出两个电子表中数据的差异
May 26 Python
python 重定向获取真实url的方法
May 11 Python
Selenium 模拟浏览器动态加载页面的实现方法
May 16 Python
解决Pycharm出现的部分快捷键无效问题
Oct 22 Python
python matplotlib库直方图绘制详解
Aug 10 Python
python实现证件照换底功能
Aug 20 Python
python 如何区分return和yield
Sep 22 Python
Python 操作SQLite数据库的示例
Oct 16 Python
python中实现词云图的示例
Dec 19 Python
Python实现发送与接收邮件的方法详解
Mar 28 #Python
Python实现线程状态监测简单示例
Mar 28 #Python
python实现朴素贝叶斯分类器
Mar 28 #Python
详解Python中where()函数的用法
Mar 27 #Python
Django基于ORM操作数据库的方法详解
Mar 27 #Python
利用Python批量提取Win10锁屏壁纸实战教程
Mar 27 #Python
Django学习笔记之ORM基础教程
Mar 27 #Python
You might like
php模拟socket一次连接,多次发送数据的实现代码
2011/07/26 PHP
php中简单的对称加密算法实现
2017/01/05 PHP
javascript CSS画图之基础篇
2009/07/29 Javascript
使用Firebug对js进行断点调试的图文方法
2011/04/02 Javascript
JS 操作符整理[推荐收藏]
2011/11/15 Javascript
Javascript在IE和FireFox中的不同表现简析
2012/12/03 Javascript
全面兼容的javascript时间格式化函数(比较实用)
2014/05/14 Javascript
JS实现密码框根据焦点的获取与失去控制文字的消失与显示效果
2015/11/26 Javascript
JavaScript实现图片滑动切换的代码示例分享
2016/03/06 Javascript
JQuery validate插件Remote用法大全
2016/05/15 Javascript
js判断是否为空和typeof的用法(详解)
2016/10/07 Javascript
JavaScript如何实现图片懒加载(lazyload) 提高用户体验(增强版)
2016/11/30 Javascript
Bootstrap select下拉联动(jQuery cxselect)
2017/01/04 Javascript
jQuery EasyUI的TreeGrid查询功能实现方法
2017/08/08 jQuery
解决Linux无法正常安装与卸载Node.js的方法
2018/01/19 Javascript
关于单文件组件.vue的使用
2018/09/20 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
express如何解决ajax跨域访问session失效问题详解
2019/06/20 Javascript
[42:36]DOTA2上海特级锦标赛B组败者赛 VG VS Spirit第二局
2016/02/26 DOTA
Python使用Pycrypto库进行RSA加密的方法详解
2016/06/06 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
2018/01/11 Python
Java与Python两大幸存者谁更胜一筹呢
2018/04/12 Python
python面试题Python2.x和Python3.x的区别
2019/05/28 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
Python3+selenium配置常见报错解决方案
2020/08/28 Python
Python实现哲学家就餐问题实例代码
2020/11/09 Python
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
详解移动端h5页面根据屏幕适配的四种方案
2020/04/15 HTML / CSS
英国领先的男士美容护发用品公司:Mankind
2016/08/31 全球购物
师范院校学生自荐信范文
2013/12/27 职场文书
岳麓书院导游词
2015/02/03 职场文书
2015年幼儿园后勤工作总结
2015/04/25 职场文书
2015年城市管理工作总结
2015/05/23 职场文书
网络妈妈观后感
2015/06/08 职场文书
2015年学校总务工作总结
2015/07/20 职场文书
梳理总结Python开发中需要摒弃的18个坏习惯
2022/01/22 Python