python 網路程式設計粘包解決方案2 + ftp上傳 + socketserver
阿新 • • 發佈:2018-11-11
一。struct
神奇的打包工具 struct
程式碼:
import struct num = 156 #將int型別的資料打包成4個位元組的資料 num_stru = struct.pack('i',num) print(len(num_stru)) print(num_stru) print('11111111111111111111111111111111') #在通過int型別解包,將前面打包的資料解包成打包之前的int資料 num2 = struct.unpack('i',num_stru) #解包出來是個元組 print(num2)#(156,) print(num2[0])
粘包的另一種情況: .第一次服務端傳送的資料比我客戶端設定的一次接收訊息的大小要大,那麼接收不完,第二次再接收的時候,就會將第一次剩餘的訊息接收到
處理粘包情況的方案二:
程式碼:
服務端
import socket import subprocess import struct server = socket.socket() ip = ('192.168.15.142',8003) server.bind(ip) server.listen() coon,addr = server.accept()
while 1: from_client_msg= coon.recv(1024).decode('utf-8') sub_obj = subprocess.Popen(from_client_msg,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True) server_cmd_msg = sub_obj.stdout.read() cmd_msg_len = len(server_cmd_msg) msg_len_stru = struct.pack('i',cmd_msg_len) coon.send(msg_len_stru) coon.sendall(server_cmd_msg)
客戶端
import struct import socket client = socket.socket() server_ip = ('192.168.15.142',8003) client.connect(server_ip) while 1: msg = input('請輸入指令:') client.send(msg.encode('utf-8')) from_server_msglen = client.recv(4) unpack_len_msg = struct.unpack('i',from_server_msglen)[0] recv_msg_len = 0 all_msg = b'' while recv_msg_len < unpack_len_msg: every_recv_data = client.recv(1024) all_msg += every_recv_data recv_msg_len += len(every_recv_data) print(all_msg.decode('gbk'))
二。 ftp 上傳方案程式碼:
程式碼:
簡單版ftp上傳服務端示例:
import socket import struct import json import os tcp_server = socket.socket() ip_port = ('127.0.0.1',8001) #127.0.0.1本機的迴環地址,供內部程式之間測試用的 tcp_server.bind(ip_port) tcp_server.listen() #客戶端上傳的檔案路徑,都放在這個路徑下 client_file_path = r'D:\jj' conn,addr = tcp_server.accept() #首先接收到檔案資訊長度轉換出來的4個位元組的資料 file_info_stru = conn.recv(4) #解包檔案資訊的長度 file_info_len = struct.unpack('i',file_info_stru)[0] #然後接收檔案的描述資訊 client_file_info = conn.recv(file_info_len).decode('utf-8') #將接收到的json字串反序列化 abc_file_info = json.loads(client_file_info) print('abc_file_info>>>',abc_file_info) client_file_size = abc_file_info['file_size'] recv_all_size = 0 #拼接一下全路徑 client_full_path = client_file_path + '\\' + abc_file_info['file_name'] # client_full_path = os.path.join(client_file_path,abc_file_info['file_name']) with open(client_full_path,'wb') as f: while recv_all_size < client_file_size: every_recv_data = conn.recv(1024) f.write(every_recv_data) recv_all_size += len(every_recv_data) conn.send('小夥玩的行,上傳成功!'.encode('utf-8')) conn.close() tcp_server.close()
簡單版ftp上傳客戶端示例:
import socket import struct import os import json tcp_client = socket.socket() server_ip_port = ('127.0.0.1',8001) tcp_client.connect(server_ip_port) read_size = 1024 file_info = { 'file_path':r'D:\python_workspace\day030\aaa.mp4', 'file_name':'aaa.mp4', 'file_size':None, } #獲取檔案大小 file_size = os.path.getsize(file_info['file_path']) #將檔案大小新增到檔案資訊的字典中 file_info['file_size'] = file_size #因為我們要傳送的資料是位元組型別,那麼必須將字典轉換為bytes型別,但是字典不能直接轉換為bytes,所以我們想到了json, #通過json模組將字典型別的檔案資訊資料轉換為了json型別的字串 file_info_json = json.dumps(file_info) #獲取了字串的長度 file_info_len = len(file_info_json) #將長度打包為4個位元組的資料, file_info_stru = struct.pack('i',file_info_len) #將打包好的4個自己的資料和我的檔案資訊資料一起傳送給了服務端 tcp_client.send(file_info_stru) tcp_client.send(file_info_json.encode('utf-8')) #統計檔案資料 all_file_data = b'' #統計檔案資料長度 all_size_len = 0 with open(file_info['file_path'],'rb') as f: while all_size_len < file_size: every_read_data = f.read(read_size) all_file_data += every_read_data all_size_len += len(every_read_data) #傳送每次讀取的資料 tcp_client.send(every_read_data) print(tcp_client.recv(1024).decode('utf-8')) tcp_client.close()
三。socketserver
作用:能夠讓服務端和多個客戶端互動
程式碼:
服務端
import socketserver #1 定義一個類 class MyServer(socketserver.BaseRequestHandler): #2 類裡面繼承socketserver.BaseRequestHandler # 3 類裡面定義一個handle方法,handle名稱不能變 def handle(self): while 1: # self.request #conn連結通道 from_client_data = self.request.recv(1024).decode('utf-8') print(from_client_data) server_input = input('明巍sb說>>>') self.request.send(server_input.encode('utf-8')) # self.request.close() if __name__ == '__main__': #服務端的IP地址和埠 ip_port = ('127.0.0.1',8001) socketserver.TCPServer.allow_reuse_address = True #繫結IP地址和埠,並且啟動我定義的上面這個類 server = socketserver.ThreadingTCPServer(ip_port,MyServer) #永久的給我執行下去 server.serve_forever()
客戶端
import socket tcp_client = socket.socket() server_ip_port = ('127.0.0.1',8001) tcp_client.connect(server_ip_port) while 1: client_msg = input('大陽哥>>>') tcp_client.send(client_msg.encode('utf-8')) from_server_msg = tcp_client.recv(1024).decode('utf-8') print(from_server_msg)