粘包现象和解决方法
一.缓冲区
缓冲区:将程序和网络解耦(类似于cpu和硬盘需要内存来缓冲一样)
输入缓冲区
输出缓冲区
二.subprocess和struct模块的简单认识
import subprocess sub_obj = subprocess.Popen( "dir", # cmd指令 shell=True, stdout = subprocess.PIPE, #正确的指令存放位置 stderr = subprocess.PIPE # 错误的指令存放位置 )
print(sub_obj.stdout.read().decode("gbk")) # read 拿到的是字节,需要解码(需要解码的字节是系统默认的)
import struct a = 10 byt = struct.pack("i",a) # 将int类型的a打包成4个字节长度的二进制 a1 = struct.unpack("i",byt) # 将byt解包成一个int类型,返回的是一个元组
三.两种粘包现象(TCP)
1.连续(发送数据间隔短)两个小的数据流会被优化算法给组合到一起并发送,造成粘包
模拟粘包现象服务端
import socket server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() from_client_msg1 = conn.recv(1024) print(from_client_msg1) from_client_msg2 = conn.recv(1024) print(from_client_msg2)
模拟粘包现象客户端
import socket client = socket.socket() client.connect(("127.0.0.1",8888)) to_send1 = client.send(b"123") to_send2 = client.send(b"123")
2.一个大的数据流过大,超过revc的值,那么会一次接收不完,暂时存放在缓冲区,下次再接收的时候就会拿到一六的数据,造成粘包
模拟粘包现象服务端
import socket import subprocess server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024).decode("utf-8") # 一次只能接收1024b 剩下的存在缓冲区 第二次再接收会粘包 sub_obj = subprocess.Popen( from_client_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) to_client_res = sub_obj.stdout.read() print(len(to_client_res)) conn.send(to_client_res)
模拟粘包现象客户端
import socket client = socket.socket() ip_port = ("127.0.0.1",8888) client.connect(ip_port) while 1: cmd = input("请输入cmd指令:").encode("utf-8") # 输入ipconfig -all client.send(cmd) server_cmd_res = client.recv(1024).decode("gbk") print(server_cmd_res)
四.产生粘包的原因及解决方案
1.产生粘包的原因:接收方不知道消息之间的界限,不知道一次性提取多少数据造成的
2.解决粘包现象的方案:自定义一个长度报头
解决粘包现象服务端
import socket import subprocess import struct server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024).decode("utf-8") sub_obj = subprocess.Popen( from_client_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # print(sub_obj.stdout.read()) sub_res = sub_obj.stdout.read() cmd_len = len(sub_res) cmd_len_byt = struct.pack("i",cmd_len) conn.send(cmd_len_byt + sub_res)
解决粘包现象客户端
import socket import struct client = socket.socket() client.connect(("127.0.0.1",8888)) while 1: cmd = input("请输入cmd指令:").encode("utf-8") client.send(cmd) cmd_len_byt = client.recv(4) cmd_len = struct.unpack("i",cmd_len_byt)[0] cmd_msg = client.recv(cmd_len).decode("gbk") print(cmd_msg)