功能:
1、获取文件列表
2、上传文件
3、下载文件
4、退出
第一部分,TftpServer部分。
①导入相关模块
1
2
3
4
5
|
from socket import * import os import signal import sys import time |
②确定文件路径
1
2
|
# 文件库路径 FILE_PATH = "/home/tarena/" |
③建立一个类,用来实现服务器功能模块
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
|
class TftpServer( object ): def __init__( self , connfd): self .connfd = connfd def do_list( self ): # 获取列表 file_list = os.listdir(FILE_PATH) # 如果对应的路径内没有文件,返回Empty if not file_list: self .connfd.send( 'Empty' .encode()) return # 路径存在文件,向客户端发送OK else : self .connfd.send(b 'OK' ) time.sleep( 0.1 ) files = "" for file in file_list: # 排除以'.'开头的隐藏文件 if file [ 0 ] ! = '.' and \ os.path.isfile(FILE_PATH + file ): files = files + file + '#' # 返回文件列表 self .connfd.send(files.encode()) # 下载文件功能 def do_get( self , filename): try : fd = open (FILE_PATH + filename, 'rb' ) except : self .connfd.send( "File doesn't exist" .encode()) return # 如果能正常打开,发送OK self .connfd.send(b "OK" ) time.sleep( 0.1 ) # 开始发送文件 try : for line in fd: self .connfd.send(line) fd.close() except Exception as e: print (e) time.sleep( 0.1 ) self .connfd.send(b '##' ) print ( "File send over" ) # 开始上传文件 def do_put( self , filename): try : fd = open (FILE_PATH + filename, 'w' ) except : self .connfd.send( "Some error" ) # 如果能正常打开文件,则发送OK self .connfd.send(b 'OK' ) # 开始发送 while True : # data为文件内容 data = self .connfd.recv( 1024 ).decode() if data = = "##" : break fd.write(data) fd.close() print ( "上传完毕" ) |
④主流程控制
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
|
def main(): # 创建套接字/地址/端口 HOST = '0.0.0.0' PORT = 8888 ADDR = (HOST, PORT) sockfd = socket() # 设置端口可重用 sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1 ) # 绑定地址 sockfd.bind(ADDR) # 设置监听队列大小 sockfd.listen( 5 ) signal.signal(signal.SIGCHLD, signal.SIG_IGN) print ( "Listen to port 8888...." ) while True : try : connfd, addr = sockfd.accept() except KeyboardInterrupt: sockfd.close() sys.exit( "Server exit" ) except Exception as e: print (e) continue print ( "Client login:" , addr) # 创建父子进程 pid = os.fork() if pid < 0 : print ( "Process creation failed" ) continue elif pid = = 0 : # 子进程负责请求接收和发送,所以节省资源,关闭连接套字 sockfd.close() tftp = TftpServer(connfd) # 接收客户端请求 while True : data = connfd.recv( 1024 ).decode() if not data: continue # 调用do_list方法获取文件列表 elif data[ 0 ] = = 'L' : tftp.do_list() # data ==> G filename # 文件名以G开头,以空格为间隔发送过来 elif data[ 0 ] = = 'G' : filename = data.split( ' ' )[ - 1 ] tftp.do_get(filename) elif data[ 0 ] = = 'P' : filename = data.split( ' ' )[ - 1 ] tftp.do_put(filename) elif data[ 0 ] = = 'Q' : print ( "客户端退出" ) sys.exit( 0 ) else : connfd.close() continue |
⑤运行主控制流程,等待客户端连接
1
2
|
if __name__ = = "__main__" : main() |
第二部分,TftpClient
①导入相关模块
1
2
3
|
from socket import * import sys import time |
②实现基本的请求功能
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
|
class TftpServer( object ): def __init__( self , sockfd): self .sockfd = sockfd def do_list( self ): self .sockfd.send(b "L" ) # 发送请求类型 # 等待接收服务器端确认 data = self .sockfd.recv( 1024 ).decode() if data = = 'OK' : data = self .sockfd.recv( 4096 ).decode() files = data.split( '#' ) for file in files: print ( file ) print ( "%%%%%There is file list%%%%%\n" ) else : # 失败的原因由服务器发送过来 print (data) def do_get( self , filename): self .sockfd.send(( 'G ' + filename).encode()) data = self .sockfd.recv( 1024 ).decode() if data = = 'OK' : fd = open (filename, 'w' ) while True : data = self .sockfd.recv( 1024 ).decode() if data = = "##" : break fd.write(data) fd.close() print ( "%s Download over\n" % filename) else : print (data) def do_put( self , filename): try : fd = open (filename, 'rb' ) except : print ( "There is no such file" ) return self .sockfd.send(( "P " + filename).encode()) data = self .sockfd.recv( 1024 ).decode() if data = = 'OK' : for line in fd: self .sockfd.send(line) fd.close() time.sleep( 0.1 ) self .sockfd.send(b '##' ) print ( "%s upload over" % filename) else : print (data) def do_quit( self ): self .sockfd.send(b 'Q' ) |
③主流程控制
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
|
# 套接字连接 def main(): if len (sys.argv) < 3 : print ( "argv is error" ) return HOST = sys.argv[ 1 ] PORT = int (sys.argv[ 2 ]) ADDR = (HOST, PORT) sockfd = socket() sockfd.connect(ADDR) tftp = TftpServer(sockfd) # tftp对象调用请求方法 while True : print ( "=======命令选项========" ) print ( "******* list *********" ) print ( "*******get file ******" ) print ( "*******put file ******" ) print ( "******* quit *********" ) print ( "======================" ) cmd = input ( "请输入命令>>" ) if cmd.strip() = = 'list' : tftp.do_list() elif cmd[: 3 ] = = "get" : filename = cmd.split( ' ' )[ - 1 ] tftp.do_get(filename) elif cmd[: 3 ] = = "put" : filename = cmd.split( ' ' )[ - 1 ] tftp.do_put(filename) elif cmd.strip() = = "quit" : tftp.do_quit() sockfd.close() sys.exit( "Welcome" ) else : print ( "Enter the right order!!!" ) continue |
④运行客户端
1
2
|
if __name__ = = "__main__" : main() |
第三部分,展示
一下就不做逐一显示,如有问题,烦请之处修正,共同进步!
原文链接:https://blog.csdn.net/weixin_42122355/article/details/80791857