gpt4 book ai didi

Docker:每个作为容器运行的客户端服务器程序无法使用 POSIX 套接字 API 相互通信

转载 作者:行者123 更新时间:2023-12-02 18:41:31 26 4
gpt4 key购买 nike

问题描述及重现步骤:我有一个用 C++ 编写的服务器程序,使用 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 返回的错误代码是“111”,这意味着连接被拒绝。

我的理解是因为两个容器即 server1 和 cli1 都连接到同一个用户定义网络“user_def_nw”桥接网络,它们应该能够通过 Socket 相互通信。但是这里连接 API 本身无法与服务器建立连接。

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

2) 我将我的基础镜像制作为 ubuntu,并在其顶部安装了 g++ 编译器,然后将我的客户端和服务器程序作为独立的容器运行,仍然出现与上面报告的相同的错误。

请帮我解决这个问题。

最佳答案

在用户定义的网络中,您可以通过引用容器名称来连接两个容器。在您的客户端应用程序 dockerfile 中,尝试将 0.0.0.0 替换为 server1。

关于Docker:每个作为容器运行的客户端服务器程序无法使用 POSIX 套接字 API 相互通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37518977/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com