socket網路編程:socket、socketserver
socket:{server,client}
socket_server示例:
1 import socket # 匯入模塊 2 server = socket.socket() #實體化一個server 3 server.bind(('localhost', 6969)) # 系結監聽的地址和埠 4 server.listen() # 開始監聽 5 while True: # 回圈等待客戶端的連接,當一個連接斷開后,繼續等待下個客戶端的連接 6 coon, addr = server.accept() # 等待客戶端的連接,當有客戶端連接時,conn,addr才有值 7 while True: # 回圈接收客戶端的資料 8 data = https://www.cnblogs.com/sunnytomorrow/p/coon.recv(1024) #接收客戶端的資料,接收資料大小為1K 9 print("server recv:", data.decode()) #接收到的資料型別為b,需要decode 10 if not data: # 如果無資料,則代表客戶端斷開 11 print("client is lost...") 12 break # 與客戶端斷開,等待下次客戶端的連接 13 coon.send(data.upper()) # 向客戶端發送資料,注意將發送的資料encode(),此處data即為b型別,所以不需要 14 server.close() # 實體關閉
socket_client示例:
import socket #匯入模塊 client = socket.socket() # 創建客戶端實體 client.connect(('localhost', 6969)) # 實體連接服務端地址及埠 while True: # 回圈接收用戶輸入并發送 msg = input(">>:").strip() # 等待用戶輸入 if len(msg.strip()) == 0: # 如果用戶輸入為空,則繼續讓用戶輸入 continue client.send(msg.encode("utf-8")) # 將用戶輸入發送只server端 data = https://www.cnblogs.com/sunnytomorrow/p/client.recv(1024) # 接收server端發送的資料 print("recv:", data.decode()) client.close() # 客戶端關閉
應用:
1、 使用socket實作類似ssh登錄后執行命令的操作
socket_ssh_server
1 import socket,os,time # 匯入模塊 2 server = socket.socket() # 實體化server 3 server.bind(('localhost',9999)) # server系結地址和埠 4 server.listen() # 監聽 5 while True: 6 conn, addr = server.accept() # 等待客戶端的連接 7 print("new conn:",addr) 8 while True: 9 print("等待新指令") 10 data = https://www.cnblogs.com/sunnytomorrow/p/conn.recv(1024) # 接收客戶端的指令 11 if not data: 12 print("客戶端已斷開") 13 break 14 print("執行指令:",data) 15 cmd_res = os.popen(data.decode()).read() #使用os.popen執行收到的指令,回傳結果賦值給cmd_res 16 print("before send",len(cmd_res)) # 輸出命令的長度 17 if len(cmd_res) ==0: # 如果指令結果長度為0,則沒此命令 18 cmd_res = "cmd has no output..." 19 conn.send( str(len(cmd_res.encode())).encode("utf-8")) #先發大小給客戶端 20 conn.recv(1024) # 等待客戶端確認,防止發送指令大小和發送結果出現粘包現象 21 conn.send(cmd_res.encode("utf-8")) # 發送指令輸出結果 22 print("send done") 23 server.close()
socket_ssh_client
1 import socket # 匯入模塊 2 client = socket.socket() # 實體化客戶端 3 client.connect(('localhost', 9999)) # 連接服務端 4 while True: # 回圈接收用戶輸入 5 data = https://www.cnblogs.com/sunnytomorrow/p/input(">>:").strip() 6 if len(data) == 0:continue 7 client.send(data.encode("utf-8")) # 發送指令 8 result_data_size = client.recv(1024) # 接收執行回傳結果的大小 9 print(result_data_size.decode()) 10 client.send(b"please send cmd result") 11 recv_data_size = 0 12 recv_data = https://www.cnblogs.com/sunnytomorrow/p/b"" 13 while recv_data_size < int(result_data_size.decode()): # 當指令結果大小大于1024時,回圈接收指令結果 14 recv_data_block = client.recv(1024) 15 recv_data_size += len(recv_data_block) 16 recv_data += recv_data_block 17 else: 18 print(recv_data_size) 19 print(recv_data.decode()) 20 client.close()
2、 使用socket實作檔案發送并計算MD5值
socket_file_server
1 import socket, os, hashlib #匯入模塊 2 server = socket.socket() 3 server.bind(("localhost", 9999)) 4 server.listen() 5 while True: 6 conn, addr = server.accept() 7 print("新連接:", addr) 8 while True: 9 print("等待指令") 10 data = https://www.cnblogs.com/sunnytomorrow/p/conn.recv(1024) 11 if not data: 12 print("客戶端已斷開") 13 break 14 filename = data.split()[1] 15 print("檔案名:", filename) 16 m = hashlib.md5() 17 if os.path.isfile(filename): 18 file_size = os.stat(filename).st_size 19 conn.send(str(file_size).encode()) 20 conn.recv(1024) 21 print("等待接收端確認") 22 f = open(filename, "rb") 23 for line in f: 24 m.update(line) 25 conn.send(line) 26 f.close() 27 conn.send(m.hexdigest().encode()) 28 print("file send done") 29 server.close()
socket_file_client
1 import socket, hashlib 2 client = socket.socket() 3 client.connect(("localhost", 9999)) 4 while True: 5 cmd = input(">>:").strip() 6 if len(cmd) == 0:continue 7 if cmd.startswith("get"): 8 client.send(cmd.encode()) 9 filename = cmd.split()[1] 10 res_filesize = client.recv(1024).decode() 11 print("檔案總大小是",res_filesize) 12 client.send("please send".encode()) 13 m = hashlib.md5() 14 recv_size = 0 15 f = open(filename+"new","wb") 16 while recv_size < int(res_filesize): 17 if int(res_filesize) - recv_size > 1024: # 解決檔案發送與MD5發送的粘包問題 18 size = 1024 19 else: 20 size = int(res_filesize) - recv_size 21 data =https://www.cnblogs.com/sunnytomorrow/p/ client.recv(size) 22 recv_size += len(data) 23 m.update(data) 24 f.write(data) 25 else: 26 print("檔案接收完畢,源檔案大小%s,已接收檔案大小%s" % (res_filesize,recv_size)) 27 old_file_md5 = client.recv(1024).decode() 28 f.close() 29 print("new file md5: ", m.hexdigest()) 30 print("old file md5: ", old_file_md5) 31 client.close()
3、 socketserver示例
socketserver_server
1 import socketserver # 匯入模塊 2 class MyTcpSocketServer(socketserver.BaseRequestHandler): # 創建一個類,繼承socketserver.BaseRequestHandler 3 def handle(self): # 重寫handle方法 4 print(self.client_address) 5 while True: 6 try: #抓取客戶端斷開的例外 7 self.data = https://www.cnblogs.com/sunnytomorrow/p/self.request.recv(1024).strip() # 接收客戶端的資料 8 self.request.send(self.data.upper()) # 發送資料給客戶端 9 except ConnectionResetError as e: 10 print("Error:", e) 11 break 12 13 if __name__ == "__main__": 14 HOST, PORT = "localhost", 9889 15 print(">>>>等待新連接>>>>") 16 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTcpSocketServer) #實體化,ThreadingTCPServer可以實作多用戶同時互動 17 server.serve_forever() # 永久接收客戶端的請求
socketserver_client:直接使用socket模塊即可
1 import socket 2 client = socket.socket() 3 client.connect(("localhost",9889)) 4 while True: 5 data = https://www.cnblogs.com/sunnytomorrow/p/input(">>:").strip() 6 if len(data) == 0:continue 7 client.send(data.encode()) 8 recv_data = https://www.cnblogs.com/sunnytomorrow/p/client.recv(1024) 9 print(recv_data) 10 client.close()
進階
使用面向物件實作客戶端檔案上傳到服務器端
socketserver_server
1 import socketserver,json,os # 匯入模塊 2 3 class MyTcpServer(socketserver.BaseRequestHandler): # 創建socketserver類 4 5 def put(self,*args): # 接收檔案函式 6 file_dic = args[0] 7 filename = file_dic["filename"] 8 filesize = file_dic["size"] 9 if os.path.isfile(filename): 10 f = open(filename+".new","wb") 11 else: 12 f = open(filename,"wb") 13 self.request.send(b"please send") 14 recv_size = 0 15 while recv_size < int(filesize): 16 data = https://www.cnblogs.com/sunnytomorrow/p/self.request.recv(1024) 17 f.write(data) 18 recv_size += len(data) 19 else: 20 print("接收完成") 21 22 def handle(self): # 重寫handle方法 23 while True: 24 try: 25 self.data = https://www.cnblogs.com/sunnytomorrow/p/self.request.recv(1024).strip() 26 file_dic = json.loads(self.data.decode()) 27 action = file_dic["action"] 28 if hasattr(self,action): # 使用反射 29 func = getattr(self,action) 30 func(file_dic) 31 else: 32 print("no action:", action) 33 except Exception as e: 34 print(e) 35 break 36 37 if __name__ == "__main__": 38 HOST,PORT = "localhost", 9999 39 server = socketserver.ThreadingTCPServer((HOST,PORT), MyTcpServer) 40 server.serve_forever()
socketserver_client
1 import socket,os,json # 匯入模塊 2 class MyFtpClient(object): # 定義客戶端類 3 def __init__(self): 4 self.client = socket.socket() # 客戶端初始化 5 6 def connect(self,ip,port): 7 self.client.connect((ip,port)) # 連接服務端 8 9 def interactive(self): 10 while True: # 回圈接收用戶輸入 11 cmd = input(">>:").strip() 12 if len(cmd)==0:continue 13 cmd_split = cmd.split() 14 action = cmd_split[0] 15 if hasattr(self,action): # 使用反射判斷有無用戶輸入的指令,沒有時回傳help 16 func = getattr(self,action) 17 func(cmd_split) 18 else: 19 self.help() 20 21 def help(self): 22 msg = ''' 23 ls 24 pwd 25 put filename 26 cd ../.. 27 ''' 28 print(msg) 29 def put(self,*args): # 上傳函式 30 cmd_split = args[0] 31 filename = cmd_split[1] 32 if os.path.isfile(filename): # 使用os模塊判斷檔案是否存在 33 filesize = os.stat(filename).st_size 34 file_dic = { 35 "action": "put", 36 "filename": filename, 37 "size": filesize, 38 "overridden": True 39 } 40 self.client.send(json.dumps(file_dic).encode('utf-8')) 41 self.client.recv(1024) 42 f = open(filename,"rb") 43 for line in f: 44 self.client.send(line) 45 else: 46 print("send done") 47 else: 48 print(filename,"is nor exist") 49 50 client = MyFtpClient() # 實體化客戶端 51 client.connect("localhost",9999) # 實體連接服務端 52 client.interactive() # 實體呼叫用戶互動函式
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/65136.html
標籤:Python
下一篇:矩陣乘法
