day8-socket接收大数据
问题概述
服务器端发送数据到客户端,如果服务器端发送的数据大于客户端一次接收的数据(客户端默认一次接收的大小为1024B,最大支持8192B),如果服务器端发送的数据大于8K,那么根据之前的解决思路,我们只能通过服务器端先计算发送数据的大小,然后再发送数据到客户端,而客户端可以根据服务器端发来的数据总大小,进行多次循环接收,直到全部接收完成。
优化服务器端:在发送数据前先计算数据大小再发送给客户端
import socket,os server = socket.socket() server.bind(("localhost",9986)) server.listen() while True: conn,addr = server.accept() print("new conn:",addr) while True: data = conn.recv(1024) if not data: print("客户端已断开") break print("执行指令:",data.decode()) cmd_res = os.popen(data.decode()).read() #接收的指令decode成str,命令的执行结果也是str conn.send(str(len(cmd_res.encode())).encode()) #发送执行结果的大小给客户端 #len()结果类型为int,需要转化为str后再encode变成二进制发送给客户端 if len(cmd_res) == 0: cmd_res= "cmd没有正确输出。。。。" conn.send(cmd_res.encode()) print("发送完成!")
优化客户端:循环判断(接收的数据大小等于服务端发送的总大小)
import socket client = socket.socket() client.connect(("localhost",9986)) while True: cmd_input = input(">>:") if len(cmd_input) == 0: continue client.send(cmd_input.encode()) recv_data_total_size = client.recv(1024).decode() #接收命令执行结果的总大小 print(recv_data_total_size) recv_size = 0 #客户端接收来自服务端的数据大小 recv_data = b"" #客户端接收来自服务端的数据 while recv_size < int(recv_data_total_size): #只要接收的大小小于总大小,说明还没接收完成 data = client.recv(1024) recv_size+=len(data) #每次接收到的有可能小于1024,所以必须使用len判断 recv_data += data else: print("接收完成,总共接收的大小为:",recv_size) print(recv_data.decode()) #等数据全部接收完再decode得到str形式
注意编码类型一致性问题
在服务器端发送数据时,服务器端和客户端(len(变量))len变量的类型要一致,否则将会出现客户端接收数据总大小和实际最后接收的总大小不一致的情况,因为len(中文)大小和len(中文.encode())的大小是不一样的,造成了数据不一致的问题。所以在实际的操作中,要注意这个问题。
zhongwen = "你好" yingwen = "hello" zhongwen_to_binary = zhongwen.encode() yingwen_to_binary = yingwen.encode() print("binary_zhongwen:",zhongwen_to_binary) print("binary_yingwen:",yingwen_to_binary) print("\33[35;1m中文及其二进制len长度对比\33[0m".center(40,"=")) print("zhongwen_size:",len(zhongwen)) print("binary_zhongwen_size:%s,type为:%s" %(len(zhongwen_to_binary),type(zhongwen_to_binary))) print("len():",type(len(zhongwen_to_binary))) print("\33[35;1m英文及其二进制len长度对比\33[0m".center(40,"=")) print("yingwen_size:",len(yingwen)) print("binary_yingwen_size:",len(yingwen_to_binary)) print(type(len(yingwen_to_binary))) #输出