Python:socket實現ftp程序
剛開始學習socket編程,還不是特熟練,碼了好長時間,中間遇到許多問題,記錄一下用socketserver寫ftp
server端:
1 #!/usr/bin/env python 2 3 import socketserver,os 4 5 class FTP(socketserver.BaseRequestHandler): 6 def handle(self): 7 def clientsend(filename): 8 f = open(‘/ftp/%s‘ %filename,‘w‘) 9 # while 1:10 data = self.request.recv(4096).decode("utf-8") 11 # if not data:break 12 f.write(data) 13 f.close() 14 print(‘File %s receive done!‘ % filename) 15 def clientdownload(filename): 16 f = open(‘/ftp/%s‘ %filename,‘r‘) 17 data = f.read()18 f.close() 19 self.request.sendall(data.encode("utf-8")) 20 print(‘listening connect from:‘,self.client_address) 21 listmsg = ‘list:\n1.help\t\t\tdispaly the list\n2.send file\t\tsend + filename\n3.download file\t\tdownload + filename\n4.ls\t\t\tShow files and permissions\n5.exit\n‘ 22 self.request.sendall("Welcome my ftp,input \033[34;1m‘help‘\033[0m dispaly meun".encode("utf-8")) 23 while 1: 24 try: 25 re_msg = self.request.recv(1024).decode("utf-8") 26 if not re_msg:break 27 if re_msg == ‘help‘ or re_msg == ‘?‘: 28 self.request.sendall(listmsg.encode("utf-8")) 29 elif re_msg.split()[0] == ‘send‘: 30 filename = re_msg.split()[1] 31 clientsend(filename) 32 elif re_msg.split()[0] == ‘ls‘: 33 ls_list = os.popen(‘ls -l /ftp‘).read().encode("utf-8") 34 self.request.sendall(ls_list) 35 elif re_msg.split()[0] == ‘download‘: 36 filename = re_msg.split()[1] 37 clientdownload(filename) 38 else: 39 self.request.sendall(‘Invalid value‘.encode("utf-8")) 40 finally: 41 pass 42 if __name__ == ‘__main__‘: #只有程序執行時才會觸發下面的語句,程序被導入調用時,下面的語句不會觸發 43 host = ‘192.168.101.128‘ 44 port = 2222 45 server = socketserver.ThreadingTCPServer((host,port),FTP) 46 server.serve_forever()
client端:
1 #!/usr/bin/env python 2 import socket,sys 3 4 host = ‘192.168.101.128‘ 5 port = 2222 6 7 s = socket.socket() 8 s.connect((host,port)) 9 info = s.recv(8096).decode("utf-8") 10 print(info) 11 while 1: 12 INPUT = str(input(‘input:‘)) 13 if INPUT.split()[0] == ‘send‘: 14 s.send(INPUT.encode("utf-8")) 15 filename = INPUT.split()[1] 16 f = open(filename,‘r‘) 17 file_data = f.read() 18 f.close() 19 s.sendall(file_data.encode("utf-8")) 20 print(‘file sent finished!‘) 21 elif INPUT.split()[0] == ‘download‘: 22 s.send(INPUT.encode("utf-8")) 23 filename = INPUT.split()[1] 24 f = open(filename,‘w‘) 25 data = s.recv(8096).decode("utf-8") 26 f.write(data) 27 f.close() 28 print(‘%s has been download!‘ %filename) 29 elif INPUT.split()[0] == ‘exit‘: 30 sys.exit() 31 else: 32 s.send(INPUT.encode("utf-8")) 33 data = s.recv(8096).decode("utf-8") 34 print(data) 35 s.close()
socket 僅支持單線程,socketserver 支持多線程
socketserver:
定義請求處理類時,需要繼承socketserver.BaseRequestHandler,並且需要創建新的handle()函數來處理請求
python中的socketserver模塊已經為我們初始化好了,直接調用即可
self.request.recv(bufsize).decode("utf-8") 讀取請求數據
self.request.sendall().encode("utf-8") 發送數據
self.client_address 客戶端請求的地址
server = socketserver.ThreadingTCPServer((Host,Port),FTP) 多線程!!!
server = socketserver.TCPServer((Host,Port),FTP) 單線程
server.serve_forever() 持續監聽,服務端一直運行,知道收到shutdown信號
socket:
socket.AF_UNIX 只能用於單一的Unix系統進程通信
socket.AF_INET 服務器之間網絡通信
socket.AF_INET6 IPv6
socket.SOCK_STREAM 流式socket,for TCP
socket.SOCK_DGRAM 數據報式socket,for UDP
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((Host,Port))
s.listen()
s.connect((Host,Port))
conn,address = s.accept() conn是新的套接字對象,可以用來接受和發送數據,address是客戶端的地址
s.close()
s.recv(bufsize) 接受套接字的數據,數據以字符串的形式返回,bufsize是接收的最大數據量
s.sendall(string) 嘗試發送所有數據,成功返回None,失敗則拋出異常
s.getpeername() 返回連接套接字的遠程地址,返回值通常為元組
s.gettimeout() 返回當前超時值,單位為秒,如果沒有設置超時,則為None
Python:socket實現ftp程序