ubuntu下使用docker和socket进行数据交互记录

ubuntu下使用docker和socket进行数据交互记录

概述:主要实现了在宿主机上通过8000端口传递一张图像给docker镜像,然后镜像中处理后,通过8001端口回传处理后的图像给宿主机。

第一章、构建镜像

一、dockerfile文件

1.拉取ubuntu20.04镜像
基于ubuntu20.04进行构建,拉取ubuntu20.04的指令如下:

sudo docker pull ubuntu:20.04

2.编写dockerfile文件
dockerfile写入如下:

# Dockerfile

# Base images 基础镜像

FROM ubuntu:20.04

# MAINTAINER 维护者信息
maintainer chenjun_1241370589@qq.com
# 设置超时
ENV PIP_DEFAULT_TIMEOUT=100 
# 设置环境变量以避免手动选择时区
ENV DEBIAN_FRONTEND=noninteractive


#RUN 执行以下命令
RUN apt update
RUN apt install python3 python3-pip -y
RUN apt-get install nano
# 安装必要的系统依赖项
RUN apt-get update && apt-get install -y \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libxrender-dev
RUN pip3 install --upgrade pip setuptools
RUN pip3 cache purge
RUN pip3 install opencv-python==4.5.5.62 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装 OpenCV  
RUN apt-get update && apt-get install -y \   
    libgl1-mesa-glx  # 安装 OpenGL 库  
# 其他依赖和设置


RUN pip3 install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple 
RUN apt install libgl1-mesa-glx
RUN mkdir -p /data/code/

#拷贝文件至工作文件夹
COPY test.py /data/code/test.py

#工作目录
WORKDIR /data/code/

#容器启动时执行的命令
CMD ["python3","test.py"]
二、编写docker内运行文件

1.新建test.py文件
test.py文件将被拷贝进镜像中,作为镜像内部运行文件。写入如下:

import cv2  # 导入OpenCV库
import numpy as np  # 导入NumPy库
import socket  # 导入socket库
import struct  # 导入struct库
import time

def receive_image():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建TCP/IP套接字
    server_socket.bind(('0.0.0.0', 8000))  # 绑定到本地地址和端口8000
    server_socket.listen(1)  # 监听连接
    
    print("Waiting for connection...")  # 打印等待连接信息
    client_socket, addr = server_socket.accept()  # 接受连接
    print(f"Connected to {addr}")  # 打印连接地址

    data = b""  # 初始化数据变量
    payload_size = struct.calcsize("L")  # 获取消息大小的字节数

    while len(data) < payload_size:  # 接收消息大小
        data += client_socket.recv(4096)

    packed_msg_size = data[:payload_size]  # 获取打包的消息大小
    data = data[payload_size:]  # 剩余数据
    msg_size = struct.unpack("L", packed_msg_size)[0]  # 解包消息大小

    while len(data) < msg_size:  # 接收完整消息
        data += client_socket.recv(4096)

    frame_data = data[:msg_size]  # 获取图像数据
    
    frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)  # 解码图像
    
    client_socket.close()  # 关闭客户端套接字
    server_socket.close()  # 关闭服务器套接字
    
    return frame  # 返回图像

def process_image(image):
    height, width = image.shape[:2]  # 获取图像高度和宽度
    new_height, new_width = height // 2, width // 2  # 计算新高度和宽度
    print("Process_image ok !")
    return cv2.resize(image, (new_width, new_height))  # 调整图像大小

def send_image(image):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建TCP/IP套接字
    for _ in range(5):  # 尝试5次连接
        try:
            client_socket.connect(('172.17.0.1', 8001))  # 连接到指定地址和端口
            break
        except ConnectionRefusedError:
            print("Connection refused, retrying...")
            time.sleep(2)  # 等待2秒后重试
    else:
        print("Failed to connect after 5 attempts")
        return

    _, img_encoded = cv2.imencode('.jpg', image)  # 编码图像为JPEG格式
    data = img_encoded.tobytes()  # 转换为字节数据

    client_socket.sendall(struct.pack("L", len(data)) + data)  # 发送数据
    client_socket.close()  # 关闭客户端套接字

if __name__ == "__main__":
    while True:
        # 接收图像
        received_image = receive_image()
        
        # 处理图像
        processed_image = process_image(received_image)
        
        # 发送处理后的图像
        send_image(processed_image)

其中client_socket.connect((‘172.17.0.1’, 8001)) # 连接到指定地址和端口这一行中的ip需要在宿主机运行指令:

ip addr show docker0

在这里插入图片描述
将inet后的ip填入代码中。

三、构建镜像

宿主机终端输入:

sudo docker build -t python_socket2 . -f Dockerfile

其中“python_socket2”是我自己创建的名字,自行修改。
在这里插入图片描述

第二章、宿主机代码

一、交互代码

在宿主机中写入test1.py代码,这里图像处理部分只对图像进行尺寸减半的操作,代码如下:

import cv2
import numpy as np
import socket
import struct

def send_image(image_path):
    # 读取图像
    image = cv2.imread(image_path)
    if image is None:
        print(f"无法读取图像: {image_path}")
        return

    # 创建TCP/IP套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('localhost', 8000))  # 连接到Docker容器的8000端口

    # 编码图像为JPEG格式
    _, img_encoded = cv2.imencode('.jpg', image)
    data = img_encoded.tobytes()

    # 发送数据
    client_socket.sendall(struct.pack("L", len(data)) + data)
    client_socket.close()

    print("图像已发送")

def receive_processed_image():
    # 创建TCP/IP套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('0.0.0.0', 8001))  # 绑定到本地地址和端口8001
    server_socket.listen(1)

    print("等待接收处理后的图像...")
    client_socket, addr = server_socket.accept()
    print(f"已连接到 {addr}")

    data = b""
    payload_size = struct.calcsize("L")

    while len(data) < payload_size:
        data += client_socket.recv(4096)

    packed_msg_size = data[:payload_size]
    data = data[payload_size:]
    msg_size = struct.unpack("L", packed_msg_size)[0]

    while len(data) < msg_size:
        data += client_socket.recv(4096)

    frame_data = data[:msg_size]
    
    # 解码图像
    frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)
    
    client_socket.close()
    server_socket.close()
    
    return frame

if __name__ == "__main__":
    image_path = "/home/cj/work/Docker/Yolov5DnnImage/bus.jpg"  # 替换为实际的图像路径
    send_image(image_path)
    
    processed_image = receive_processed_image()
    
    # 显示处理后的图像
    #cv2.imshow("Processed Image", processed_image)
    #cv2.waitKey(0)
    #cv2.destroyAllWindows()

    # 保存处理后的图像
    cv2.imwrite("processed_image.jpg", processed_image)
    print("处理后的图像已保存为 processed_image.jpg")

图像输入地址自行修改。

第三章、交互使用

一、docker端

在宿主机终端输入:

sudo docker run -p 8000:8000 -i -t python_socket2:latest

这里的“python_socket2:latest”修改成自己的镜像。
查看镜像宿主机终端输入:

sudo docker images

在这里插入图片描述

二、宿主机端

运行test1.py文件
在这里插入图片描述
同时在docker端也会有输出:
在这里插入图片描述
在宿主机当前工作目录下也会生成对应的图像。
在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小俊俊的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值