Как отправить данные между двумя удаленными машинами с помощью программирования сокетов? - PullRequest
0 голосов
/ 25 октября 2018

Я пытаюсь отправить данные с одного удаленного компьютера (Ubuntu) на мой домашний компьютер (High Sierra).Я прочитал a пару из вопросов здесь, в SO, но, похоже, они не дают решения моей проблемы.Я подключился к удаленному компьютеру с помощью ssh и создал и успешно скомпилировал следующие программы на обоих компьютерах.

client.cpp

#include <iostream>
#include <string>

#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char* argv[])
{
    std::string address = argv[1];
    int port = 38473;
    int success;

    // http://man7.org/linux/man-pages/man2/socket.2.html
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1)
        return errno;

    sockaddr_in socket_address{};
    socket_address.sin_family = AF_INET;
    socket_address.sin_port = htons(port);  // htons - Host to Network Short. Flip endianness to match machine.
    success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr);  // Pointer (to String) to Number.
    if (success <= 0)
        return errno;

    success = connect(server_socket, (sockaddr*)&socket_address, sizeof(socket_address));
    if (success == -1)
        return errno;

    std::cout << "Connected" << std::endl;
    for (int i = 0; i < 10; ++i)
        write(server_socket, "Hello!\n", 7);
}

server.cpp

#include <iostream>
#include <string>

#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char* argv[])
{
    std::string address = "127.0.0.1";
    int port = 38473;
    int success;

    // http://man7.org/linux/man-pages/man2/socket.2.html
    int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket == -1)
        return errno;

    sockaddr_in socket_address{};
    socket_address.sin_family = AF_INET;
    socket_address.sin_port = htons(port);  // htons - Host to Network Short. Flip endianness to match machine.
    success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr);  // Pointer (to String) to Number.
    if (success <= 0)
        return errno;

    // http://man7.org/linux/man-pages/man2/bind.2.html
    success = bind(listen_socket, (sockaddr*)&socket_address, sizeof(socket_address));
    if (success == -1)
        return errno;

    // http://man7.org/linux/man-pages/man2/listen.2.html
    success = listen(listen_socket, 10);
    if (success == -1)
        return errno;

    sockaddr_in client_address;
    socklen_t   client_address_size = sizeof(client_address);
    int client_socket = accept(listen_socket, (sockaddr*)&client_address, &client_address_size);
    if (client_socket == -1)
        return errno;

    close(listen_socket);

    size_t buffer_size = 4096;
    char buffer[buffer_size];
    ssize_t bytes_received;

    std::cout << "Connected" << std::endl;
    while (true)
    {
        memset(buffer, 0, buffer_size);
        // http://man7.org/linux/man-pages/man2/recvmsg.2.html

        if ((bytes_received = read(client_socket, buffer, buffer_size)) <= 0)
            return 0;
        std::cout << "Message: " << buffer << std::endl;
    }
}

При запуске обеих программ на одном компьютере (где исполняемый файл клиента принимает 127.0.0.1 в качестве аргумента в командной строке), он работает отлично и данные отправляются.При попытке запустить мой локальный компьютер в качестве сервера и запустить client.cpp с удаленного компьютера, я получаю код ошибки 111 (соединение отказано).

После прочтения различных учебных пособий / блогов / сообщений, похоже, что:

  1. Порт в настоящее время не прослушивает.
  2. Брандмауэр предотвращает соединение.

Я попытался решить эту проблему, выполнив следующие действия..

В настоящее время порт не прослушивается.

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

Port forwarding table

Брандмауэр предотвращает соединение.

Я удостоверился, что мой брандмауэр отключен на локальном компьютере (в Системных настройках -> Безопасность и конфиденциальность -> Брандмауэр) и сделал запись в моем маршрутизаторе, разрешающую сообщения с удаленного компьютера (используя его публичный IP-адрес)-адрес) через порт 38473.

Firewall configurations

Мне все еще не удается подключиться.Я запустил Wireshark и увидел, что пульт ДУ отправил запрос SYN, но получил взамен [RST, ACK].Флаг RST , по-видимому, позволяет брандмауэру разорвать соединение, но я не понимаю, почему он так поступил, учитывая мои предыдущие конфигурации выше.

Wireshark output

Что я делаю не так?

1 Ответ

0 голосов
/ 25 октября 2018

Настройте свой код сервера для прослушивания IP-адреса интересующей вас карты Ethernet на компьютере ИЛИ:

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);
...