功能:
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