Docker部署C++服务端与Python客户端连接失败求助
Docker下服务端与客户端连接故障排查求助
我已经花了4小时排查问题,但重复操作仍无法解决Docker环境下服务端与客户端的运行故障。我已在docker-compose中配置端口映射和暴露,但连接始终失败,且VS Code端口栏未显示该端口被占用。以下是我的配置与代码:
docker-compose.yml
services: server: build: context: . dockerfile: Dockerfile container_name: server volumes: - ./data:/app/data ports: - "3000:3000" networks: - app_network stdin_open: true tty: true client: build: context: . dockerfile: Dockerfile.client container_name: client networks: - app_network stdin_open: true tty: true networks: app_network: name: netflix_app_network driver: bridge
服务端Dockerfile
# Use an official image with CMake and GCC pre-installed FROM ubuntu:20.04 # Set environment variables to prevent interactive prompts during package installation ENV DEBIAN_FRONTEND=noninteractive # Install necessary tools and dependencies RUN apt-get update && apt-get install -y \ build-essential \ cmake \ git \ wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Copy the entire project into the container RUN mkdir -p /app/data COPY . /app # Set the working directory to the project root WORKDIR /app # Create a build directory, configure, and build the project RUN mkdir -p build && \ cd build && \ cmake .. && \ cmake --build . # Expose server's port EXPOSE 3000 VOLUME /app/data # Set the default command to run the application CMD ["./build/App"]
客户端Dockerfile(手动运行客户端)
FROM python:3.9-slim # Set the working directory in the container WORKDIR /app # Copy the client code into the container COPY . /app # Install any necessary dependencies COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt # Command to run the client program CMD ["tail", "-f", "/dev/null"]
服务端代码
#include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <iostream> #include <cstring> // For memset TCPServer::TCPServer(int port, IClientHandler* handler) : port(port), clientHandler(handler) { serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket < 0) { perror("Failed to create socket"); exit(EXIT_FAILURE); } sockaddr_in serverAddr{}; memset(&serverAddr, 0, sizeof(serverAddr)); // Clear memory serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; // Bind to all available IPv4 addresses serverAddr.sin_port = htons(port); if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { perror("Bind failed"); close(serverSocket); exit(EXIT_FAILURE); } } TCPServer::~TCPServer() { close(serverSocket); } void TCPServer::start() { if (listen(serverSocket, 5) < 0) { perror("Listen failed"); exit(EXIT_FAILURE); } std::cout << "Server listening on port " << port << std::endl; while (true) { std::cout << "hi" << port << std::endl; sockaddr_in clientAddr{}; socklen_t clientLen = sizeof(clientAddr); int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientLen); if (clientSocket < 0) { perror("Accept failed"); continue; // Continue accepting connections } clientHandler->handleClient(clientSocket); close(clientSocket); // Close the client socket after handling it } }
客户端代码
import socket class TCPClient: def __init__(self, server_address: str, port: int): self.server_address = server_address self.port = port self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def connect(self): try: self.client_socket.connect((self.server_address, self.port)) print(f"Connected to server at {self.server_address}:{self.port}") except Exception as e: print(f"Failed to connect: {e}") self.client_socket.close() raise def send(self, message: str): try: self.client_socket.sendall(message.encode('utf-8')) except Exception as e: print(f"Error sending message: {e}") def receive(self): try: response = self.client_socket.recv(1024).decode('utf-8') return response except Exception as e: print(f"Error receiving response: {e}") return None def close(self): self.client_socket.close() print("Connection closed.") if __name__ == "__main__": client = TCPClient("127.0.0.1", 3000) # Replace with the server's IP and port try: client.connect() while True: command = input("Enter command: ") client.send(command) response = client.receive() if response: print(f"Server response: {response}") except Exception as e: print(f"An error occurred: {e}") finally: client.close()
排查建议
- 修正客户端连接地址:容器内的
127.0.0.1指向自身,而非服务端容器。将客户端代码中的连接地址改为服务端容器名server,Docker Compose会在自定义网络中自动解析容器名到对应IP。 - 验证服务端状态:
- 执行
docker logs server查看日志,确认是否输出Server listening on port 3000,若没有则检查编译是否正常、./build/App是否存在。 - 进入服务端容器
docker exec -it server bash,执行netstat -tulpn确认端口3000处于监听状态。
- 执行
- 测试容器间网络连通性:
- 进入客户端容器
docker exec -it client bash,先执行ping server确认网络可达,再用telnet server 3000测试端口是否开放。
- 进入客户端容器
- 明确端口映射作用:
ports: "3000:3000"仅用于宿主机访问服务端,容器间通信无需依赖该映射,直接通过自定义网络访问即可。 - 规范客户端运行流程:客户端容器用
tail -f /dev/null保持运行,需手动进入容器执行python client.py,确保使用修正后的服务端地址。
内容的提问来源于stack exchange,提问作者Itay Derazon
相关产品推荐
相关产品推荐

