提高C ++ UDP例如无法通过互联网传输 [英] Boost C++ UDP example can not transmit over internet

查看:143
本文介绍了提高C ++ UDP例如无法通过互联网传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我尝试用升压C ++ UDP客户端 - 服务器。

我注意到自带ASIO的例子之一,并修改它一下。

它工作得非常好本地网络上,但是当我的服务器主机我们与港口正确转发服务器中的一个,这是行不通的。

我运行UDP服务器,并尝试与客户端从家里通过互联网发送但没有分组到达服务器。我相信,这些端口正确转发和防火墙没有凑了过来。

有没有本地网络和互联网之间的差异尽可能UDP通讯是什么呢?

以下是客户端和服务器的code:

---- ----客户端

 的#include< cstdlib>
#包括LT&; CString的GT;
#包括LT&;&iostream的GT;
#包括LT&;升压/ asio.hpp>使用boost ::支持ASIO ::知识产权:: UDP;
枚举{MAX_LENGTH = 1024};INT主(INT ARGC,CHAR *的argv [])
{
字符要求[MAX_LENGTH]
尝试
{    提高:: ASIO :: io_service对象io_service对象;    UDP套接字:: S(io_service对象,UDP ::端点(UDP :: V4(),0));    UDP ::解析器解析(io_service对象);
    UDP ::解析器::查询查询(UDP :: v4的(),MyPublicIp,3002);
    UDP ::解析:迭代迭代器= resolver.resolve(查询);    使用命名空间std; //函数strlen。
    性病::法院LT&;< 写给我: ;
    而(1)
    {
        的std :: cin.getline(请求MAX_LENGTH);
        为size_t request_length = strlen的(要求);
        s.send_to(提高:: ASIO ::缓​​存(请求request_length),*迭代器);        焦炭回复[MAX_LENGTH]
        UDP ::端点sender_endpoint;
        为size_t reply_length = s.receive_from(提高:: ASIO ::缓​​冲区(回复,MAX_LENGTH),sender_endpoint);
        性病::法院LT&;<说:;
        的std :: cout.write(回复,reply_length);
        性病::法院LT&;< \\ n;
        性病::法院LT&;<说什么? ;
    }
  }
  赶上(性病::例外急症)
  {
    的std :: CERR<< 例外:<< e.what()&所述;&下; \\ n;
  }
  的std :: cin.getline(请求MAX_LENGTH);
  返回0;
}

------服务器------------

 的#include<升压/ chrono.hpp>
#包括LT&; cstdlib>
#包括LT&;&iostream的GT;
#包括LT&;升压/ bind.hpp>
#包括LT&;升压/ asio.hpp>
#包括LT&;升压\\螺纹\\ thread.hpp>
#包括LT&;&的ctime GT;
使用boost ::支持ASIO ::知识产权:: UDP;级服务器
{
上市:
  服务器(提高:: ASIO :: io_service对象和放大器; io_service对象,短端口)
    :io_service_(io_service对象)
      socket_(io_service对象,UDP ::端点(升压:: ASIO ::知识产权:: address_v4 ::任何(),口))
  {
      的std ::填充(data_中的数据,data_中的数据+ MAX_LENGTH,0);
    socket_.async_receive_from(
        提高:: ASIO ::缓​​冲区(data_中的数据,MAX_LENGTH),sender_endpoint_,
        提高::绑定(安培;服务器:: handle_receive_from,为此,
          提高:: ASIO ::占位符::错误
          提高:: ASIO ::占位符:: bytes_transferred));
  }  无效handle_receive_from(常量的boost ::系统::错误_ code和;错误,
      为size_t bytes_recvd)
  {
    如果(误差放大器&;&!放; bytes_recvd大于0)
    {
        TD ::法院LT&;< 从连接:<< sender_endpoint_.address()to_string()&所述;&下; << sender_endpoint_.port()&所述;&下;的std :: ENDL;      socket_.async_send_to(
          提高:: ASIO ::缓​​冲区(data_中的数据,strlen的(data_中的数据)),sender_endpoint_,
          提高::绑定(安培;服务器:: handle_send_to,为此,
            提高:: ASIO ::占位符::错误
            提高:: ASIO ::占位符:: bytes_transferred));
    }
    其他
    {
      socket_.async_receive_from(
          提高:: ASIO ::缓​​冲区(data_中的数据,MAX_LENGTH),sender_endpoint_,
          提高::绑定(安培;服务器:: handle_receive_from,为此,
            提高:: ASIO ::占位符::错误
            提高:: ASIO ::占位符:: bytes_transferred));
    }
  }  无效handle_send_to(常量的boost ::系统::错误_ code&安培; / * *误差/,
      为size_t / * * bytes_sent /)
  {      的std ::填充(data_中的数据,data_中的数据+ MAX_LENGTH,0);
    socket_.async_receive_from(
        提高:: ASIO ::缓​​冲区(data_中的数据,MAX_LENGTH),sender_endpoint_,
        提高::绑定(安培;服务器:: handle_receive_from,为此,
          提高:: ASIO ::占位符::错误
          提高:: ASIO ::占位符:: bytes_transferred));  }私人的:
  提高:: ASIO :: io_service对象和放大器; io_service_;
  UDP ::插座socket_;
  UDP ::端点sender_endpoint_;
  枚举{MAX_LENGTH = 300};
  烧焦data_中的数据[MAX_LENGTH]
};INT主(INT ARGC,CHAR *的argv [])
{
  尝试
  {
    性病::法院LT&;< 启动服务器<<的std :: ENDL;    提高:: ASIO :: io_service对象io_service对象;
    短端口= 3002;
    使用命名空间std;
    服务器S(io_service对象,口);
    性病::法院LT&;< 服务器开始侦听端口:<<港口<<的std :: ENDL;
    io_service.run();
  }
  赶上(性病::例外急症)
  {
    的std :: CERR<< 例外:<< e.what()&所述;&下; \\ n;
  }
  返回0;
}


解决方案

从传输层的角度来看,有一个UDP本地网络和互联网之间没有什么不同。然而,也有可以发挥作用的各种因素:


  • UDP缺乏可靠性。执行一个写,同步阻塞等待响应才会有好的结果的LAN上的噪点极少的大部分时间。然而,它可能是值得修改客户端的期望的数据丢失在互联网上去时。如果应用程序将需要高度的可靠性,然后考虑不同传输层协议,例如TCP。

  • 如果服务器和客户端在同一个网络上,但客户端试图连接到通过网络的外部IP的服务器,然后验证该网关支持循环注定的外部IP后面的内部通信。

  • 执行traceroute命令验证IP信息包的存活时间领域较高足够之间的路由客户端和服务器。

  • 验证路由客户端和服务器之间的设备适当的NAT支持。 RFC 4787 详细介绍了UDP和NAT的要求。 打洞如果服务器实际上不是公开访问可能是必需的。

在大多数情况下,如果在LAN上的客户机和服务器的工作,那么它通常是一个网络的问题。这可能是值得的调试与基本工具的网络如的netcat 并使用可靠的基于连接的协议,如TCP。一旦连接已被观察到,然后交换使用UDP客户端和服务器。

Hello i am experimenting with Boost C++ UDP client-server.

I took the one of the examples that comes with ASIO and modified it a bit.

It works very well on local network but when i host the server to one of our servers with ports correctly forwarded, it doesn't work.

I run the UDP server and try to transmit with the client from home over the internet but none of the packets arrive to the server. I am sure that the ports are forwarded correctly and that the firewall is not getting in the way.

Is there any difference between local network and internet as far as UDP communication is concerned?

Following is the code of client and server:

----Client----

#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;
}

------Server------------

#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;
}

解决方案

From a transport layer perspective, there is no different for UDP between a local network and the internet. However, there are various factors that can come into play:

  • UDP lacks reliability. Performing a single write and synchronously blocking waiting for a response will have good results on a LAN with minimal noise the majority of the time. However, it may be worth modifying the client to expect data loss when going across the internet. If the applications are going to need a high degree of reliability, then consider a different transport layer protocol, such as TCP.
  • If the server and client are on the same network, but the client is trying to connect to the server through the network's external IP, then verify that the gateway supports looping back internal traffic destined to the external IP.
  • Perform a traceroute to verify the IP packet's time to live field is higher enough for routing between the client and server.
  • Verify proper NAT support for routing devices between the client and server. RFC 4787 describes UDP and NAT requirements in detail. UDP Hole Punching may be required if the server is not actually publicly accessible.

In most cases, if the client and server work on a LAN, then it is often a networking issue. It may be worth debugging networking with basic tools like netcat and using reliable connection-based protocol, such as TCP. Once connectivity has been observed, then swap to using the UDP client and server.

这篇关于提高C ++ UDP例如无法通过互联网传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆