问题描述以及重现步骤: 我有一个用C ++编写的Server程序,使用posix Socket API。用于构建服务器映像的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创建客户端映像:
$ 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是&#34; 111&#34;这意味着连接被拒绝。
我的理解是,因为两个容器即server1和cli1都连接到同一个用户定义的网络&#34; user_def_nw&#34;桥接网络,它们应该能够通过Socket相互通信。但是这里连接API本身无法与服务器建立连接。
另外,我尝试了以下内容 1)我在给定的Linux系统中将我的客户端服务器程序作为正常进程运行,它完全正常。
2)我将我的基本映像设置为ubuntu,并在其顶部安装了g ++编译器,然后将我的客户端和服务器程序作为独立容器运行,仍然出现与上述报告相同的错误。
请帮我解决这个问题。
答案 0 :(得分:0)
在用户定义的网络中,您可以通过引用其容器名称来连接两个容器。在您的客户端应用程序dockerfile中,尝试将0.0.0.0替换为server1。
答案 1 :(得分:0)
好像你正在从客户端连接错误的IP地址。 运行服务器容器
现在使用 docker network inspect bridge 命令检查实际服务器的容器IP地址
现在尝试使用此IP地址连接客户端。
我认为docker Gateway将有172.17.0.1,如果你下次运行服务器,你可能会获得172.17.0.2作为服务器的IP。
希望它能解决你的问题。
答案 2 :(得分:0)
您可以通过DNS条目(每个容器名称一个)访问同一网络中的容器。
这是一个示例进行说明。在您的情况下,您将配置客户端容器以连接到服务器DNS条目服务器(类似于下面的myserver用法)。
$ docker network create javaapp
451905b63038719be32c3029dd229d02260fdc6f5fcca136c063556d3f3714d4
$ docker run -d --net javaapp --name myserver nginx
4b8c235789b2b262190f39d1ca2495304ca4ffc84321a127ac1bb9a0b748c717
$ docker run --net javaapp nathanleclaire/curl curl myserver:80
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0
<!DOCTYPE html>
<html>`enter code here`
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>