黏包的解决方式
黏包出现的根本原因是接收方不知道要传过来多少数据,解决方法1:在传给接收方以前告诉它要传过去多少数据。 解决方法2:使用struct方法
解决方法1:传之前告诉它要传多少
#服务器端 import socket sk = socket.socket() sk.bind((‘127.0.0.1‘,8080)) sk.listen() conn,addr = sk.accept() while True: cmd = input(‘>>>‘) if cmd == ‘q‘: conn.send(b‘q‘) break conn.send(cmd.encode(‘gbk‘)) num = conn.recv(1024).decode(‘utf-8‘) # 2048 conn.send(b‘ok‘) res = conn.recv(int(num)).decode(‘gbk‘) print(res) conn.close() sk.close()
#客户端 import socket import subprocess sk = socket.socket() sk.connect((‘127.0.0.1‘,8080)) while True: cmd = sk.recv(1024).decode(‘gbk‘) if cmd == ‘q‘: break res = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out = res.stdout.read() std_err = res.stderr.read() sk.send(str(len(std_out)+len(std_err)).encode(‘utf-8‘)) #2000 sk.recv(1024) # ok sk.send(std_out) sk.send(std_err) sk.close()
这种方法的好处:确定了我要接收多大的值
1)要在文件中配置一个配置项:就是每一次recv的大小
2)当我们要发送大数据的时候,要明确的告诉接收方要发送多大的数据,以便接收方能够准确接收所有的数据。
3)用处:多用在文件传输的过程中
1、大文件的传输一定是按照字节读,每一次读固定的字节
2、传输的过程中,一边读一边传,接收端一边收一边写
3、send这个大文件之前,每一次文件总量减去固定值
4、recv这个大文件,每一次接收之后减去固定值
这种方法的不好的地方:多了一次交互
1)send\sendto,在超过一定范围的时候就会报错
2)程序的内存管理(啥意思???)
解决方法二:用struct将文件大小或者长度转化成4个字节的bytes类型
import socket import subprocess import struct #接收命令 sk=socket.socket() sk.connect((‘127.0.0.1‘,8008)) while True: cmd=sk.recv(1024).decode(‘gbk‘) ret=subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out=ret.stdout.read() std_err=ret.stderr.read() len_std=len(st_out)+len(std_err) len_num=struct.pack(‘i‘,len_std) #将执行命令后的内容长度转化成4个字节类型 sk.send(len_num) sk.send(std_out) sk.send(std_err) sk.close()
#客户端 import socket import struct sk=socket.socket() sk.bind((‘127.0.0.1‘,8008)) sk.listen() con,addr=sk.accept() while True: cmd=input(‘>>>‘) con.send(cmd.encode(‘gbk‘)) num=con.recv(4) len_by=struct.unpack(‘i‘,num)[0] #接收到的4个字节长度转化成数字,重点!!! ret=con.recv(len_by).decode(‘gbk‘) print(ret) con.close() sk.close()