粘包的原因和解决/打印进度条
socket缓冲区
输入输出一边两个缓冲区,缓冲区将程序与网络解耦
服务端为输出缓冲区,信息先进缓冲区,网络通后再走。输入的避免输入太快接受太慢导致拥塞。
取数据时的1024指的是从缓冲区里取的大小。每个缓冲区的大小由电脑的系统配置文件决定 。
粘包现象,在tcp下发生,面向消息流。
1.两个数据都很短,被在缓冲区被优化算法组合为一段内容发送
2.如果客户端一次2000b,两次4000b都在缓冲区,服务端只能1024的一次性接收,接收第一次数据的时候就把后面的一部分也合并进来了。
引入subprocess的简单使用,来模拟和解决粘包现象
第一种方法,不常用
服务端
1 import socket,subprocess 2 server = socket.socket() 3 ip_port = ('121.195.167.34',8002) 4 server.bind(ip_port) 5 server.listen() 6 conn,add = server.accept() 7 8 while 1: 9 from_client_cmd = conn.recv(1024) 10 11 print(from_client_cmd.decode('utf-8')) 12 13 sub_obj = subprocess.Popen( 14 from_client_cmd.decode('utf-8'), #这里用于接收客户端发送来的cmd语句 15 shell = True, 16 stdout = subprocess.PIPE, #运行正常信息所在的管道 17 stderr = subprocess.PIPE #报错时信息所在的管道 18 ) 19 std_msg = sub_obj.stdout.read() #打印管道内的信息 20 print('指令长度>>>>',len(std_msg)) 21 send_len = str(len(std_msg)).encode('utf-8') 22 conn.send(send_len) 23 24 status = conn.recv(1024).decode('utf-8') 25 if status == 'ok': 26 conn.send(std_msg) 27 else: 28 print(1)
客户端
1 import socket 2 client = socket.socket() 3 ip_port = ('121.195.167.34',8002) 4 client.connect(ip_port) 5 6 while 1: 7 cmd = input('请输入cmd指令:') 8 client.send(cmd.encode('utf-8')) 9 10 from_srver_msg = client.recv(1024).decode('utf-8') 11 12 print('来自服务端额信息长度:',from_srver_msg) 13 14 client.send(b'ok') 15 16 server_cmd_result = client.recv(int(from_srver_msg)) 17 18 print(server_cmd_result.decode('gbk'))
由于每次返回的字节过长导致了粘包,所以服务端先返回即将返回的字节长度
客户端获取长度,回复收到,
服务端确认后发送原内容,客户端读取对应长度的内容即可。
但是多了一次对话,效率降低
第二种:
为了避免这个多出来的一次对话,将数据前加入长度
服务端
1 import socket,subprocess,struct 2 3 server = socket.socket() 4 ip_port = ('121.195.167.34',8002) 5 server.bind(ip_port) 6 server.listen() 7 while 1: 8 conn,add = server.accept() 9 10 from_client_cmd = conn.recv(1024) 11 12 sub = subprocess.Popen( 13 from_client_cmd.decode('utf-8'), 14 shell = True, 15 stdout = subprocess.PIPE, 16 stderr = subprocess.PIPE 17 ) 18 cmd_result=sub.stdout.read() 19 20 msg_struct = struct.pack('i',len(cmd_result)) 21 22 conn.send(msg_struct+cmd_result)
客户端
1 import socket,struct 2 client = socket.socket() 3 ip_port = ('121.195.167.34',8002) 4 client.connect(ip_port) 5 while 1: 6 cmd = input('>>>:请输入指令:') 7 client.send(cmd.encode('utf-8')) 8 server = client.recv(4) 9 msg_len = struct.unpack ('i',server)[0] 10 server_result = client.recv(msg_len) 11 print(server_result.decode('gbk'))
打印进度条
1 import time 2 for i in range(0,110,10): 3 print('\r'+str(i)+'%'+(int(i/10)*'**'),end='') 4 time.sleep(1)