Docker:客户机服务器程序,每个都以Container身份运行,无法使用POSIX套接字API互相通信

问题说明与步骤重现:我有一个用C ++编写的服务器程序,使用POSIX套接字API。 用于构build服务器映像的Dockerfile是:

$ cat Dockerfile FROM gcc:4.9 WORKDIR /home/vikrana COPY . . EXPOSE 1001 RUN g++ -o testcplusplus testprogram.cpp ENV PATH /home/vikrana:$PATH ENTRYPOINT ["testcplusplus", "1001"] 

以下是服务器程序:

 #include <iostream> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <cstring> #include <cstdlib> #include <arpa/inet.h> #include <netdb.h> #include <errno.h> using namespace std; int main(int argc, char *argv[]) { int sockfd, newsockfd, portno; socklen_t clilen; char buffer[256]; struct sockaddr_in serv_addr, cli_addr; int n; if(const char* env_p = std::getenv("PATH")) std::cout << "Your PATH is: " << env_p << '\n'; if(argc < 2) { cout<<"Number of arguments not correct\n"; exit(1); } cout<<argv[1]<<"\n"; cout<<"Creating socket\n"; struct protoent *proto; proto = getprotobyname("tcp"); sockfd=socket(AF_INET, SOCK_STREAM, proto->p_proto); cout<<"Socket created successfully\n"; portno=atoi(argv[1]); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr("0.0.0.0"); cout<<"Port No:"<<portno<<"\n"; serv_addr.sin_port=htons(portno); cout<<"Starting binding socket to a port\n"; if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { cout<<"Error while binding\n"; exit(1); } cout<<"Bind is successful\n"; cout<<"Listening to port\n"; int x =listen(sockfd,5); if(x<0) { cout<<"Error on listening to port 1001\n"; cout<<errno<<"\n"; cout<<strerror(errno)<<"\n"; close(sockfd); exit(1); } clilen=sizeof(cli_addr); cout<<"Accepting connection\n"; newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); if(newsockfd <0) { cout<<"Error while accepting a new connection\n"; close(sockfd); exit(1); } cout<<"Accepted the connection\n"; while(true) { memset(&buffer,0,sizeof(buffer)); cout<<"Reading from socket to buffer\n"; n=read(newsockfd,buffer,255); if(n<0) { cout<<"Erro reading from socket\n"; close(sockfd); close(newsockfd); exit(1); } cout<<"Message received to the server:"<<buffer<<"\n"; n=write(newsockfd,"I got your message\n",19); if(n<0) { cout<<"Error writing into socket\n"; close(sockfd); close(newsockfd); exit(1); } } close(sockfd); close(newsockfd); return 0; } 

以下是我用来在容器中运行我的服务器程序的Docker命令:

  $ docker run --net=user_def_nw -ti -P --name server1 my-server-app 

在运行上面的命令时,容器被附加到user_def_nw,并且IP地址被分配给容器。

另一方面,以下是使用posix Socket API以C ++编写的客户端程序的详细信息。 DockerFile创build客户端映像:

 $ cat Dockerfile FROM gcc:4.9 WORKDIR /home/vikrana COPY . . RUN g++ -o testcplusplus testclientprogram.cpp ENV PATH /home/vikrana:$PATH ENTRYPOINT ["testcplusplus", "0.0.0.0", "1001"] 

以下是客户端程序的代码:

 #include <iostream> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <cstring> #include <cstdlib> #include <arpa/inet.h> #include <errno.h> #include <netdb.h> using namespace std; int main(int argc, char *argv[]) { int sockfd, newsockfd, portno; struct sockaddr_in server; char message[256], server_reply[2000]; if(const char* env_p = std::getenv("PATH")) std::cout << "Your PATH is: " << env_p << '\n'; struct protoent *proto; proto = getprotobyname("tcp"); sockfd=socket(AF_INET, SOCK_STREAM, proto->p_proto); cout<<"socket created\n"; cout<<argv[1]<<"\n"; cout<<argv[2]<<"\n"; portno=atoi(argv[2]); cout<<portno<<"\n"; server.sin_family=AF_INET; server.sin_addr.s_addr=inet_addr(argv[1]); server.sin_port=htons(portno); memset(server.sin_zero, '\0', sizeof server.sin_zero); cout<<"connecting to server\n"; int x =connect(sockfd, (struct sockaddr *)&server, sizeof(server)); cout<<"Connect Return Code:"<<x<<"\n"; if(x<0) { cout<<"Connect Failed\n"; cout<<errno<<"\n"; cout<<strerror(errno)<<"\n"; exit(1); } cout<<"Connected\n"; while(1) { cout<<"Enter Message:"; cin>>message; if(send(sockfd,message,strlen(message),0) < 0) { cout<<"Send Failed\n"; exit(1); } sleep(2); if(recv(sockfd,server_reply,2000,0) < 0) { cout<<"Recv Failed\n"; break; } cout<<"Server Reply:"<<server_reply<<"\n"; } close(sockfd); return 0; } 

以下是我用来在容器中运行我的客户端程序的Docker命令:

  $ docker run --net=user_def_nw -ti --name cli1 my-client-app 

在运行上述命令时,注意到客户端无法连接到侦听端口1001的服务器。

错误代码返回我的连接API是“111”,这意味着连接被拒绝。

我的理解是,既然容器即server1和cli1连接到同一个用户定义的networking“user_def_nw”桥接networking,它们应该能够通过Socket互相通信。 但是这里连接API本身没有build立与服务器的连接。

此外,我尝试了以下1)我运行我的客户端服务器程序作为一个正常的进程在给定的Linux系统,它工作得很好。

2)我做了我的基础镜像作为Ubuntu和顶部它安装​​了g ++编译器,然后运行我的客户端和服务器程序作为独立的容器,仍然是相同的错误报告上述我越来越。

请帮我解决这个问题。

在用户定义的networking中,可以通过引用其容器名称来连接两个容器。 在您的客户端应用程序dockerfile中,尝试用server1replace0.0.0.0。

好像你是从客户端连接错误的IP地址。 运行你的服务器容器

现在使用docker network inspect bridge命令检查实际服务器的容器IP地址

现在尝试使用此IP地址连接客户端。

我认为docker网关将有172.17.0.1,如果你运行服务器,你可能得到172.17.0.2作为服务器的IP。

希望它能解决你的问题。