先记录一个能实现的,基于base64进行编码传输;
但由于编解码大于传输整张图像的时间,所以准备直接传输。
不编码直接传输:
- 直接可以
s.sendto(np_array,addr)
,对方接收的为bytes; - 采用
a = np.frombuffer(datas,dtype=np.uint8,offset=0)
,第三个参数表示舍弃前offset个; - 注意:需要设置
np.set_printoptions(threshold=1e10)
,不然大的array转str的时候会直接省略号; - 发送的array过大,且需要解析;需要分包发,然后对方分包接收,解析,然后合并。
- (1)解析bytes:按字符解析;
- (2)合并bytes,再转numpy: 新建
datas = b''
,然后每个包解析后取需要的bytes,然后+=就好了。注意:发送的时候image需要转换为uint8,不然默认为8byte,转化后才是一个数字对应一个byte。image = image.astype(np.uint8)
- 11.24补充,对于丢包问题,采用多进程:进程1进行收取,put进queue中;进程2对数据进行queue.get(),这个的问题在于如果queue中存储太多,会累计延迟;所以需要定时清理queue。继续增加一个进程,一个列队;p1只进行判ip执行recvfrom,收到的包put到que1;p2只进行que1.get然后解析与拼接包,完整img就put到que2;p3进行que2.get然后进行图像处理。 注意: que.put时间可能比rece长。
- 需要对Linux的socket的最大接收缓存进行设置,然后在代码中进行修改
s.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,512*512*1024)
sysctl -a | grep rmem
修改配置文件:sudo gedit /etc/sysctl.conf
添加:
net.core.rmem_max = 51210241024 #设置512M
执行配置:sysctl -p
- [ ]
base64编码传输
client
def socket_client(filepath,ip = '127.0.0.1:8888'):
try:
# 1、创建socket通信对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2、使用正确的ip和端口去链接服务器
s.connect((ip.split(':')[0],int(ip.split(':')[1])))
except socket.error as msg:
print(msg)
sys.exit(1)
# print (s.recv(1024))
print('tcp 协议')
BASE64 = 1
recvData = None
while 1:
if os.path.isfile(filepath):
img = cv2.imread(filepath,0)
start_t = time.time()
if BASE64:
# #编码成base64
# fp = open(filepath, 'rb')
# imgData = base64.b64encode(fp.read())
img_str = cv2.imencode('.jpg', img)[1].tostring() # 将图片编码成流数据,放到内存缓存中,然后转化成string格式
imgData = base64.b64encode(img_str) # 编码成base64
else:
#不编码
imgData = img.tostring()
s.send(imgData)
print('send time:',(time.time() - start_t)*1000)
# 接收服务器的响应(服务器回复的消息)
recvData = s.recv(1024).decode('utf-8')
# print('客户端收到服务器回复的消息:%s' % (recvData))
end_t = time.time()
# 4、关闭socket对象
s.close()
return "%.3f ms"%((end_t - start_t)*1000),recvData
def socket_client_udp(filepath,ip = '127.0.0.1:8888'):
print('udp 协议')
BASE64 = 1
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
if os.path.isfile(filepath):
img = cv2.imread(filepath,0)
start_t = time.time()
if BASE64:
img_str = cv2.imencode('.jpg', img)[1].tostring() # 将图片编码成流数据,放到内存缓存中,然后转化成string格式
imgData = base64.b64encode(img_str) # 编码成base64
else:
#不编码
imgData = img.tostring()
s.sendto(imgData,(ip.split(':')[0],int(ip.split(':')[1])))
print('send time:%.6f ms'%((time.time() - start_t)*1000))
recvData,addr = s.recvfrom(2048)
end_t = time.time()
s.close()
return "%.3f ms"%((end_t - start_t)*1000),recvData.decode('utf-8')
server
def socket_service_tcp(model_path = 'epoch29.pth',ip = '127.0.0.1:8888'):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ip.split(':')[0],int(ip.split(':')[1])))
# s.bind(("127.0.0.1",8888))
s.listen(5)
except socket.error as msg:
print(msg)
sys.exit(1)
TEST = ModelTest(model_path)
print ("Waiting...")
while 1:
conn, addr = s.accept()
t = threading.Thread(target=deal_data, args=(conn, addr,TEST))
t.start()
def deal_data(conn, addr,TEST):
print ('Accept new connection from {0}'.format(addr))
BASE64 = 1
while 1:
if BASE64:
data = conn.recv(5000)
#base64编码
data = base64.b64decode(data)
nparr = np.frombuffer(data, dtype=np.uint8)
cvImg = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
else:
data = conn.recv(40000)
cvImg = np.fromstring(data,dtype=np.uint8)
cvImg.shape = 200,200
# print(cvImg.shape,cvImg)
#deal img
result = TEST.startPredict(cvImg)
# 给socket服务器发送信息
send_data = str(result)
conn.send(send_data.encode('utf-8'))
conn.close()
break
def socket_service_udp(model_path = 'epoch29.pth',ip = '127.0.0.1:8888'):
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind((ip.split(':')[0],int(ip.split(':')[1])))
TEST = ModelTest(model_path)
BASE64 = 1
while True:
if BASE64:
data,addr = s.recvfrom(5000)
#base64编码
data = base64.b64decode(data)
nparr = np.frombuffer(data, dtype=np.uint8)
cvImg = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
else:
data ,addr= s.recvfrom(40000)
cvImg = np.fromstring(data,dtype=np.uint8)
cvImg.shape = 200,200
print ('Accept new connection from {0}'.format(addr))
#deal img
result = TEST.startPredict(cvImg)
result = (str(result)).encode('utf-8')
s.sendto(result,addr)