Отказ удаленного сокета хоста Docker-контейнера - PullRequest
0 голосов
/ 05 мая 2019

Я пытаюсь передать простое сообщение между моим хост-компьютером и моим док-контейнером.

Я начал с создания своего док-контейнера с сетевым драйвером хоста:
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

Я сделал файл в ~ / Documents / tcp_server.c в своем контейнере со следующим кодом:

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.\n\n");
    }

    // 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: %s\n", server_response);

    // Avoiding data leaks
    close(network_socket);

    return 0;
}

К сожалению, я не получил "Its-a me, a-Mario!", а скорее «Произошла ошибка при подключении к удаленному сокету».

Я полагал, что отлично связал два, используя соответствующие IP-адреса и идентичные номера портов, но, похоже, я этого не сделал.Пожалуйста, дайте мне знать, если у вас есть какие-либо указания относительно моего затруднительного положения.

Редактировать: Обновить!Я установил Netcat на свой контейнер и установил соединение между моим хостом и моим контейнером.
Хост: $ nc -l 9001
Контейнер: $ nc localhost 9001
Любое сообщение, отправленное из контейнера в следующем приглашении, достигает моего хоста, который говорит мне, что это исключительно ошибка с моим кодом.

1 Ответ

0 голосов
/ 05 мая 2019

На самом низком уровне ваш серверный код привязывается (2) к 192.168.0.9, но ваш клиентский код подключается (2) к 172.17.0.1.Сервер будет принимать соединения только с тем адресом, к которому он привязан.Если вы используете Docker для работы в сети, серверный процесс неотличим от любого другого процесса, выполняющегося на хосте с сетевой точки зрения, и хотя 172.17.0.1, вероятно, также достигнет хоста, поскольку это не совсем тот же адрес,Ваше соединение будет отклонено.

Если сервер работает в контейнере Docker, а клиент работает непосредственно на том же хосте:

  1. bind (2) до 0.0.0.0.(Привязка к 127.0.0.1 сделает процесс недоступным снаружи контейнера; частный IP-адрес контейнера непредсказуем.)
  2. Не запускать контейнер с --net host.Запустите его с соответствующей опцией -p, сопоставляющей порт контейнера с некоторым портом хоста;например, -p 9001:9001.
  3. С клиента, работающего не в Docker, на том же хосте, подключите (2) к порту 127.0.0.1 9001. С другого хоста (Docker)или иным образом), используйте имя первого хоста.

Если клиент работает в другом контейнере на том же хосте:

  1. bind (2) до 0.0.0.0.
  2. docker create network something.Вам не нужны никакие дополнительные аргументы, но вам нужно создать сеть.
  3. Когда вы docker run оба контейнера, запустите их с --net something, совпадающим с сетью, которую вы ранее создали, и полезным --name.
  4. В клиенте используйте getaddrinfo (3), чтобы найти имя контейнера сервера;затем подключите (2) к этому sockaddr.

Обратите внимание, что ни один из этих путей не включает поиск частного IP-адреса контейнера (за исключением случаев, когда детали низкого уровня вобычный путь "connect to this hostname").Это меняется регулярно (всякий раз, когда вы удаляете и воссоздаете контейнер), недоступно из внешнего хоста и даже недоступно из консоли хоста в некоторых настройках Docker.Нет необходимости искать это.

Также обратите внимание, что ни один путь не включает docker exec.Это полезный инструмент отладки, но обычно он не является частью основного рабочего процесса контейнера.(Если вы обнаружите, что «docker run контейнер, а затем сразу docker exec», как правило, вы должны изменить последовательность запуска контейнера, чтобы сделать то, что docker exec является самим собой.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...