当前位置: 首页 > 后端技术 > Python

WebSocket实现【服务端】向【客户端】发送图片和字符串消息

时间:2023-03-25 20:00:42 Python

最近在项目中需要模仿服务端:服务端不断的以字符串的形式向客户端发送图片及其参数,而客户端接收这些信息进行处理,然后将处理结果返回给服务器。在网上找了很多socket代码,还是只能发送字符串信息,不支持图片传输;或者client向server发送图片,因为一般的逻辑是先启动server再启动client,所以干脆把图片发给server把主体换成server也很奇怪,因为这样只有client可以首先开始。最后我选择了socket。工作完成后,我不是很满意。主要是我需要先启动client再启动server,感觉很别扭。【完成】。不甘心,几经周折,终于找到了python的WebSocket方法(之前只知道Java有WebSocket),代码比socket简单,并且让服务端主动向客户端发送数据,就是适合我的需要。虽然这段代码只能传输简单的字符串,但我愿意改一下。WebSocket是一种通过单个TCP连接进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换更加容易,允许服务器主动向客户端推送数据。Socket是一个比较底层的接口,只能传输字节格式的数据。但是WebSocket`是一个应用层协议,可以传输其他格式的数据(其实到达底层后也需要解析成字节),比如json。但是除了传图片我还需要传字符串。如果我用json,我要么打包成字典再转成json,要么发两个json,感觉乱七八糟。最好直接传两个字节。numpy图片和字符串转成bytes字节流的方法可以参考上一篇文章。server.pyimportasyncioimportwebsocketsimportcv2asyncdefecho(websocket,path):video_path='D:/test/ccc/mp4/1.mp4'#视频路径cap=cv2.VideoCapture(video_path)#读取视频fps=cap.get(cv2.CAP_PROP_FPS)#获取视频的帧率whileTrue:k=0whilecap.isOpened():success,frame=cap.read()ifsuccess:k+=1ifk%(fps*4)==0:#每隔4s发送一帧图片#将numpy图片转换为bytesbytestream_,img_encode=cv2.imencode('.jpg',frame)img_data=img_encode.tobytes()#将string字符串转换为bytes字节流img_name=(str(k)+'.jpg').encode()#持续发送消息awaitwebsocket.send(img_data)awaitwebsocket.send(img_name)print('%3d.jpg发送成功,休眠1秒'%k)awaitasyncio.sleep(1)#睡眠1秒cap.release()if__name__=='__main__':start_server=websockets.serve(echo,'127.0.0.1',6666)#换成自己的地址asyncio.get_event_loop().run_until_complete(start_server)asyncio.get_event_loop().run_forever()client.pyimportasyncioimportwebsocketsimportnumpy作为npiportcv2importosasyncdefhello(uri):asyncwithwebsockets.connect(uri)aswebsocket:os.makedirs('./save',exist_ok=True)whileTrue:img_data=awaitwebsocket.recv()#接收消息img_name=awaitwebsocket.recv()#接收消息#将图片字节码字节转换成一维numpy数组放入缓存img_buffer_numpy=np.frombuffer(img_data,dtype=np.uint8)#从指定内存缓存读取一维numpy数据,并将数据转换(解码)为图像矩阵格式frame=cv2.imdecode(img_buffer_numpy,1)name=img_name.decode()cv2.imwrite('./save/'+name,frame)print('接收成功',name)if__name__=='__main__':asyncio.get_event_loop().run_until_complete(hello('ws://127.0.0.1:6666'))#换成自己的地址,先运行server.py,再运行client.py,效果:关于报错:websockets.exceptions.ConnectionClosedError:code=1006(connectionclosedabnormally[internal]),无原因解决:在client.py中的connect函数中添加参数如下:websockets.connect(uri,ping_interval=None)在server.py中的serve函数中添加相同的参数:websockets.serve(echo,'127.0.0.1',6666,ping_interval=无)