本文实例讲述了Python实现的FTP通信客户端与服务器端功能。分享给大家供大家参考,具体如下:
一 代码
1、服务端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
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、客户端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
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