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获取单个程序CPU使用情况趋势图
Mar 10 Python
对python的文件内注释 help注释方法
May 23 Python
Python中关键字global和nonlocal的区别详解
Sep 03 Python
Python爬取成语接龙类网站
Oct 19 Python
python常用函数与用法示例
Jul 02 Python
浅析python中while循环和for循环
Nov 19 Python
Python+OpenCV实现将图像转换为二进制格式
Jan 09 Python
Python 3.8 新功能大揭秘【新手必学】
Feb 05 Python
什么是python的必选参数
Jun 21 Python
Python如何使用vars返回对象的属性列表
Oct 17 Python
Lombok插件安装(IDEA)及配置jar包使用详解
Nov 04 Python
浅谈python数据类型及其操作
May 25 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模拟post提交数据方法汇总
2016/02/16 PHP
浅析php静态方法与非静态方法的用法区别
2016/05/17 PHP
PHP迭代与递归实现无限级分类
2017/08/28 PHP
Laravel 5.5基于内置的Auth模块实现前后台登陆详解
2017/12/21 PHP
javascript 函数调用的对象和方法
2010/07/01 Javascript
jquery操作select option 的代码小结
2011/06/21 Javascript
JQuery魔力之$("tagName")与selector
2012/03/05 Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
2013/04/19 Javascript
js读取json的两种常用方法示例介绍
2014/10/19 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
2015/10/09 Javascript
JS采用绝对定位实现回到顶部效果完整实例
2016/06/20 Javascript
Angular2生命周期钩子函数的详细介绍
2017/07/10 Javascript
利用jquery如何从json中读取数据追加到html中
2017/12/01 jQuery
JQuery通过后台获取数据遍历到前台的方法
2018/08/13 jQuery
Koa代理Http请求的示例代码
2018/10/10 Javascript
jquery分页插件pagination使用教程
2018/10/23 jQuery
Vue 使用formData方式向后台发送数据的实现
2019/04/14 Javascript
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
Django数据库操作的实例(增删改查)
2017/09/04 Python
使用Eclipse如何开发python脚本
2018/04/11 Python
python 以16进制打印输出的方法
2018/07/09 Python
python 分离文件名和路径以及分离文件名和后缀的方法
2018/10/21 Python
Python Pandas数据中对时间的操作
2019/07/30 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
Python函数参数类型及排序原理总结
2019/12/19 Python
tensorflow将图片保存为tfrecord和tfrecord的读取方式
2020/02/17 Python
Keras之自定义损失(loss)函数用法说明
2020/06/10 Python
python实现图像外边界跟踪操作
2020/07/13 Python
Python调用JavaScript代码的方法
2020/10/27 Python
美国最大的城市服装和运动鞋零售商:Jimmy Jazz
2016/11/19 全球购物
能否解释一下XSS cookie盗窃是什么意思
2012/06/02 面试题
C#实现启动一个进程
2016/10/01 面试题
迟到检讨书300字
2014/02/14 职场文书
网络工程师自荐书范文
2014/04/01 职场文书
幼儿园六一亲子活动方案
2014/08/26 职场文书
写给医生的感谢信
2015/01/22 职场文书