缓冲区
将程序和网络解耦
什么是黏包
只有TCP有黏包现象,UTP永远没有黏包现象
两种黏包的现象:
1.连续的小包可会被优化算法给组合到一起进行发送
2.第一次如果发送的数据大小2000B接收端一次性接收大小为1024,这就是导致剩下的内容会被下一次recv接收到,导致结果混乱
第一种产生黏包,大于接收值时就会产生黏包
import socket client = socket.socket() client.connect(('127.0.0.1',8001)) while 1: cmd = input('请输入指令:') client.send(cmd.encode('utf-8')) server_cmd_result = client.recv(1024) print(server_cmd_result.decode('gbk'))
import socket import subprocess server = socket.socket() ip_port = ('127.0.0.1',8001) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024) print(from_client_cmd.decode('utf-8')) sub_obj = subprocess.Popen( from_client_cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) std_msg = sub_obj.stdout.read() print('指令的执行结果长度>>>>',len(std_msg)) conn.send(std_msg)
第二种产生黏包,同时发生信息产生黏包
import socket BUFSIZE = 1024 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) res = s.connect(('127.0.0.1',8001)) s.send('hi'.encode('utf-8')) s.send('alex'.encode('utf-8'))
from socket import * tcp_socket_server = socket(AF_INET,SOCK_STREAM) ip_port = ('127.0.0.1',8001) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr = tcp_socket_server.accept() data1 = conn.recv(10) data2 = conn.recv(10) print('----->',data1.decode('utf-8')) print('----->',data2.decode('utf-8')) conn.close()
解决方案一:由于双方不知道对方发送的长度,导致接收的时候可能接收不全,或者多接收另外一次发送的信息内容,所以所以在发送真实数据之前,要先发送数据长度,接收端根据长度接收后面真实数据,但是双方有一个交互确认的过程
import socket client = socket.socket() client.connect(('127.0.0.1',8001)) while 1: cmd = input('请输入指令:') client.send(cmd.encode('utf-8')) server_cmd_len = client.recv(1024).decode('utf-8') print('来自服务端的信息长度',server_cmd_len) client.send(b'ok') server_cmd_result = client.recv(int(server_cmd_len)) print(server_cmd_result.decode('gbk'))
import socket import subprocess server = socket.socket() ip_port = ('127.0.0.1',8001) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024) print(from_client_cmd.decode('utf-8')) sub_obj = subprocess.Popen( from_client_cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) std_msg = sub_obj.stdout.read() std_msg_len = len(std_msg) std_bytes_len = str(len(std_msg)).encode("utf-8") print('指令的执行结果长度>>>>',len(std_msg)) conn.send(std_bytes_len) status = conn.recv(1024) if status.decode('utf-8') == 'ok': conn.send(std_msg) else: pass
解决方案二: struct模块
打包:struct.pack('i',长度)
解包:struct.unpack('i',字节)
# -*- coding:utf-8 -*- import socket import struct client = socket.socket() client.connect(('127.0.0.1',8008)) while 1: cmd = input('请输入指令:') client.send(cmd.encode("utf-8")) server_res_len = client.recv(4) msg_len = struct.unpack('i',server_res_len)[0] print("来自服务端的信息长度:",msg_len) server_cmd_result = client.recv(msg_len) print(server_cmd_result.decode('gbk'))
# -*- coding:utf-8 -*- import socket import subprocess import struct server = socket.socket() ip_port = ('127.0.0.1',8008) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024) print(from_client_cmd.decode('utf-8')) sub_obj = subprocess.Popen( from_client_cmd.decode('utf-8'), shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE, ) std_msg = sub_obj.stdout.read() std_msg_len = len(std_msg) print("指令的长度>>>",len(std_msg)) msg_lenint_struct = struct.pack('i',std_msg_len) conn.send(msg_lenint_struct+std_msg)
进度条的打印
import time for i in range(20): print('\r' + i*'*',end='') time.sleep(0.2)