Python implements FTP communication software

a code

1. Server code
import socket
import threading
import them
import struct
#User account, password, home directory
#You can also store this information in the database
users = {'zhangsan':{'pwd':'zhangsan1234', 'home':r'c:\python 3.5'},
         'lisi': {'pwd': 'lisi567', 'home': 'c: \\'}}
def server(conn,addr, home):
    print('New client: '+str(addr))
    # Enter the current user home directory
    os.chdir(home)
    while True:
        data = conn.recv(100).decode().lower()
        #Display each command entered by the client
        print(data)
        #client exit
        if data in ('quit', 'q'):
            break
        #View the file list of the current folder
        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)
        #Switch to the previous directory
        elif ''.join(data.split()) == 'cd..':
            cwd = os.getcwd()
            newCwd = cwd[:cwd.rindex('\\')]
            #Consider the case of the root directory
            if newCwd[-1] == ':':
                newCwd + = '\\'
            #limit user home directory
            if newCwd.lower().startswith(home):
                os.chdir(newCwd)
                conn.send(b'ok')
            else:
                conn.send(b'error')
        #View the current directory
        elif data in ('cwd', 'cd'):
            conn.send(str(os.getcwd()).encode())
        elif data.startswith('cd '):
            #Specify the maximum number of separations, considering the case where the target folder has spaces
            #Only allow jumps using relative paths
            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')
        #download file
        elif data.startswith('get '):
            data = data.split(maxsplit=1)
            #Check if the file exists
            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)
                    #end of sending file
                    if not content:
                        conn.send(b'overxxxx')
                        break
                    #Send file content
                    conn.send(content)
                    if conn.recv(10) == b'ok':
                        continue
                fp.close()
            else:
                conn.send(b'no')
        # invalid command
        else:
            pass
            
    conn.close()
    print(str(addr)+'close connection')
#Create Socket, listen to the local port, wait for the client to connect
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 10600))
sock.listen(5)
while True:
    conn, addr = sock.accept()
    #Verify that the username and password entered by the client are correct
    userId, userPwd = conn.recv(1024).decode().split(',')
    if userId in users and users[userId]['pwd'] == userPwd:
        conn.send(b'ok')
        #Create and start a thread for each client connection, the parameters are connection, client address, client home directory
        home = users[userId]['home']
        t = threading.Thread(target=server, args=(conn,addr,home))
        t.daemon = True
        t.start()
    else:
        conn.send(b'error')
 
 
2. Client code
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()
 
二 运行结果
客户端运行结果


 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327104148&siteId=291194637