我正在尝试在主机计算机和docker容器之间传达一条简单的消息。
我首先使用主机网络驱动程序创建我的Docker容器:
docker run -t -d --network host --name cfalcon ubuntu
接下来我进入容器:
docker exec -it cfalcon
我将主机IP确定为192.168.0.109,并且我的容器的IP为172.17.0.1使用:
hostname -I
我在我的容器中使用以下代码在我的容器中撰写文件:
tcp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char* argv[]) {
char address[] = "192.168.0.109";
// Creating Server Socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// Defining Server Address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
// Specify the port, 9001 seems safe
server_address.sin_port = htons(9001);
server_address.sin_addr.s_addr = inet_addr(address);
// Binding our Socket to our Specified IP, 192.168.0.109
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
// Listen() Function Begins Listening for a Connection
listen(server_socket, 1);
// Ability to Accept Connections
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
char server_message[256] = "Its-a me, a-mario!";
// Send a message with send()
send(client_socket, server_message, sizeof(server_message), 0);
close(server_socket);
return 0;
}
返回我的主机机器,我决定在〜/documents/tcp_client.c上使用以下代码制作一个新文件:
tcp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char* argv[]) {
char address[] = "172.17.0.1";
// Creating a Socket
int network_socket;
// socket(domain of socket (generally AF_INET, a constant), TCP socket, protocol)
network_socket = socket(AF_INET, SOCK_STREAM, 0);
// Specifying an Address for the Socket (Address family is same as parameter one of socket())
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
// Specify the port, 9001 seems safe
server_address.sin_port = htons(9001);
server_address.sin_addr.s_addr = inet_addr(address);
// Returns an integer for error handling
int connection_status = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
// Error Handling
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket.nn");
}
// If we send data, we receive a response from the server in recv
char server_response[256];
recv(network_socket, &server_response, sizeof(server_response), 0);
// Printing the Server's Response
printf("The server responded with: %sn", server_response);
// Avoiding data leaks
close(network_socket);
return 0;
}
不幸的是,我没有收到"我,我,a-mario!&quot",而是"相反,"有一个错误,与远程插座连接。
我相信我使用相应的IP和相同的端口号完美地链接了这两者,但似乎没有。如果您对我的困境有任何指导,请告诉我。
编辑:更新!我在容器上安装了Netcat,并在主机和容器之间建立了连接。
主机:$ nc -l 9001
容器:$ nc localhost 9001
从以下提示中发送从容器发送的任何消息都到达我的主机机器,这告诉我这完全是我的代码的错误。
在最低级别,您的服务器代码 bind (2(至192.168.0.9,但是您的客户端代码 connect (2(至172.17.0.1。服务器只会接受与其绑定的单个地址的连接。如果您使用的是Docker主机网络,则服务器过程与从网络的角度在主机上运行的任何其他过程都没有区别,而172.17.0.1也可能会达到主机,因为它不是完全相同的地址,而是您的连接将被拒绝。
如果服务器在Docker容器中运行,并且客户端直接在同一主机上运行:
- 绑定(2(至0.0.0.0。(与127.0.0.1结合将使该过程无法从容器外部进行;容器私有的IP地址是不可预测的。(
- 请勿使用
--net host
启动容器。请使用适当的-p
选项将容器端口映射到某些主机端口。例如,-p 9001:9001
。 - 来自客户端,不在docker,在同一主机上运行, connect (2(至127.0.0.1端口9001。从其他主机(Docker或其他(使用第一个主机的名称。
如果客户端在同一主机上的其他容器中运行:
- bind (2(to 0.0.0.0。
-
docker create network something
。您不需要任何其他参数,但是您确实需要创建网络。 - 当您
docker run
两个容器时,请使用与您先前创建的网络相匹配的--net something
和有用的--name
。 - 在客户端中,使用 getAddrinfo (3(查找服务器的容器名称;然后连接(2(到该
sockaddr
。
请注意,这些路径都不涉及查找集装箱私有的IP地址(除了普通的"连接到此主机名"路径中的低级细节除外(。这是例行更改(每当您删除和重新创建容器时(,无法从户外访问,甚至无法从某些Docker设置上的主机控制台访问。永远不需要查找这个。
还要注意,这两种路径均涉及docker exec
。这是一个有用的调试工具,但通常不是核心容器工作流程的部分。(如果您发现自己" docker run
A容器,然后立即docker exec
",通常应该更改容器启动序列以执行docker exec
的任何事情本身。(