Socket接收大数据
上一篇博客中的简单ssh实例,就是说当服务器发送至客户端的数据,大于客户端设置的数据,则就会把数据服务端发过来的数据剩余数据存在IO缓冲区中,这样就会造成我们想要获取数据的完整性。
解决思路:
1、改大客户端接收的数据的大小,因为官方建议最多只能接收8k的数据,那服务端发送过来的数据很容易就会大于8K,这个思路并不能从根本上解决问题(不建议使用)
2、客户端可以多收几次,服务端给客户端发数据之前,先计算一下要发给客户端数据大小(len()判断文件长度) ,比如说要发给客户端数据是5k大小,先把5K这个值发送给客户端,客户端知道总共会接收5K的值,就知道需要接收多少次了,循环接收,直到5k数据全部接收完毕为止。
思路2逻辑流程图:
服务端代码:
import socket,os server = socket.socket() server.bind(("localhost",9999)) server.listen(5) while True: conn,addr = server.accept() print("new addr:",addr) while True: data = conn.recv(1024) if not data: print("客户端已断开") break print("执行指令:",data) cmd_res = os.popen(data.decode()).read() print("before send:",len(cmd_res)) if len(cmd_res) == 0: cmd_res = "cmd has no output...." conn.send( str(len(cmd_res.encode())).encode() ) #发送服务端发送给客户端数据的长度 conn.send(cmd_res.encode("utf-8")) #发送服务端的数据 print("send done") server.close()
客户端代码:
import socket client = socket.socket() client.connect(("localhost",9999)) while True: cmd = input(">>>:").strip() if len(cmd) == 0:continue client.send(cmd.encode("utf-8")) cmd_res_size = client.recv(1024) #接收命令的长度 print("命令结果大小:",cmd_res_size.decode()) recevied_size = 0 #接收客户端发来数据的计算器 recevied_data = b'' #客户端每次发来内容的计数器 while recevied_size < int(cmd_res_size.decode()): #当接收的数据大小 小于 客户端发来的数据 cmd_res = client.recv(1024) recevied_size += len(cmd_res) #每次收到的服务端的数据有可能小于1024,所以必须用len判断 recevied_data += cmd_res else: print(recevied_data.decode("utf-8","ignore")) print("cmd res receive done ....",recevied_size) client.close()
通过思路2写出的代码就能解决上一篇博客简单ssh实例中数据展示不完整的问题,效果图:
中文字符的坑:
通过上面代码实验后会发现客户端准备接收数据的大小会和实际数据大小不一样,实际数据要比客户端接收的数据要大,如图:
这是因为python用计算中文字符,按字符和字节算的话,长度的值是不一样的,一个 中文字符=3个字节, 如图 :