Arhn - архитектура программирования

Пример Boost C++ UDP не может передавать через Интернет

Здравствуйте, я экспериментирую с клиент-сервером Boost C++ UDP.

Я взял один из примеров, поставляемых с ASIO, и немного изменил его.

Он очень хорошо работает в локальной сети, но когда я размещаю сервер на одном из наших серверов с правильно перенаправленными портами, он не работает.

Я запускаю сервер UDP и пытаюсь передать клиенту из дома через Интернет, но ни один из пакетов не приходит на сервер. Я уверен, что порты проброшены правильно и что брандмауэр не мешает.

Есть ли разница между локальной сетью и Интернетом в отношении UDP-связи?

Ниже приведен код клиента и сервера:

----Клиент----

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::udp;
enum { max_length = 1024 };

int main(int argc, char* argv[])
{
char request[max_length];
try
{

    boost::asio::io_service io_service;

    udp::socket s(io_service, udp::endpoint(udp::v4(), 0));

    udp::resolver resolver(io_service);
    udp::resolver::query query(udp::v4(), "MyPublicIp", "3002");
    udp::resolver::iterator iterator = resolver.resolve(query);

    using namespace std; // For strlen.
    std::cout << "Write to me: ";
    while(1)
    {
        std::cin.getline(request, max_length);
        size_t request_length = strlen(request);
        s.send_to(boost::asio::buffer(request, request_length), *iterator);

        char reply[max_length];
        udp::endpoint sender_endpoint;
        size_t reply_length = s.receive_from(boost::asio::buffer(reply, max_length), sender_endpoint);
        std::cout << Say:";
        std::cout.write(reply, reply_length);
        std::cout << "\n";
        std::cout << Say What?" ;
    }
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }
  std::cin.getline(request, max_length);
  return 0;
}

------ Сервер ------------

#include <boost/chrono.hpp>
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost\thread\thread.hpp>
#include <ctime>
using boost::asio::ip::udp;

class server
{
public:
  server(boost::asio::io_service& io_service, short port)
    : io_service_(io_service),
      socket_(io_service, udp::endpoint( boost::asio::ip::address_v4::any(), port))
  {
      std::fill(data_, data_ + max_length, 0);
    socket_.async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint_,
        boost::bind(&server::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive_from(const boost::system::error_code& error,
      size_t bytes_recvd)
  {
    if (!error && bytes_recvd > 0)
    {
        td::cout  << "Connection from: " << sender_endpoint_.address().to_string() << " " << sender_endpoint_.port() << std::endl;

      socket_.async_send_to(
          boost::asio::buffer(data_, strlen(data_)), sender_endpoint_,
          boost::bind(&server::handle_send_to, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
    else
    {
      socket_.async_receive_from(
          boost::asio::buffer(data_, max_length), sender_endpoint_,
          boost::bind(&server::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
  }

  void handle_send_to(const boost::system::error_code& /*error*/,
      size_t /*bytes_sent*/)
  {  

      std::fill(data_, data_ + max_length, 0);
    socket_.async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint_,
        boost::bind(&server::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));

  }

private:
  boost::asio::io_service& io_service_;
  udp::socket socket_;
  udp::endpoint sender_endpoint_;
  enum { max_length = 300 };
  char data_[max_length];
};

int main(int argc, char* argv[])
{
  try
  {
    std::cout << "Starting server" << std::endl;

    boost::asio::io_service io_service;
    short port = 3002;
    using namespace std; 
    server s(io_service, port);
    std::cout << "Server started. Listening on port:" <<port << std::endl;
    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }
  return 0;
}

  • Попробуйте телнет сервер. telnet MyPublicIp 3002. Проблем может быть много. Возможно, ваш компьютер блокирует связь. Возможно, ваш провайдер блокирует его. 14.04.2013
  • Наиболее вероятное объяснение заключается в том, что переадресация портов на самом деле настроена неправильно или между вами и сервером существует больше слоев NAT, чем вы думаете. 14.04.2013
  • Ну, я не могу подключиться по телнету, так как использую UDP. Есть ли способ узнать, в какой момент пакеты отбрасываются? 14.04.2013
  • Может ли кто-нибудь, у кого есть открытые порты UDP, попробовать приведенный выше код и передать через Интернет? 14.04.2013

Ответы:


1

С точки зрения транспортного уровня для UDP между локальной сетью и Интернетом нет никакой разницы. Тем не менее, есть различные факторы, которые могут вступить в игру:

  • UDP не отличается надежностью. Выполнение одиночной записи и синхронная блокировка в ожидании ответа будут иметь хорошие результаты в локальной сети с минимальным уровнем шума в большинстве случаев. Однако, возможно, стоит изменить клиент, чтобы он ожидал потери данных при переходе через Интернет. Если приложениям потребуется высокая степень надежности, рассмотрите другой протокол транспортного уровня, например TCP.
  • Если сервер и клиент находятся в одной сети, но клиент пытается подключиться к серверу через внешний IP-адрес сети, убедитесь, что шлюз поддерживает зацикливание внутреннего трафика, направленного на внешний IP-адрес.
  • Выполните трассировку, чтобы убедиться, что значение поля время жизни IP-пакета достаточно для маршрутизации между клиентом и сервер.
  • Проверьте правильную поддержку NAT для маршрутизации устройств между клиентом и сервером. RFC 4787 подробно описывает требования UDP и NAT. Пробивка отверстий UDP может потребоваться, если сервер на самом деле не является общедоступным.

В большинстве случаев, если клиент и сервер работают в локальной сети, проблема часто связана с сетью. Возможно, стоит отладить сеть с помощью базовых инструментов, таких как netcat, и использовать надежный протокол на основе соединения, такой как ПТС. Как только подключение будет установлено, переключитесь на использование клиента и сервера UDP.

14.04.2013
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..