【问题标题】:asynchronous UDP client/server communication (BOOST) - server does not read异步 UDP 客户端/服务器通信 (BOOST) - 服务器不读取
【发布时间】:2015-04-19 19:54:53
【问题描述】:

您好,我一直在尝试实现一个简单的服务器/客户端应用程序以通过 UDP 套接字进行通信并了解 UDP 如何使用 boost 库工作,我的问题是 async_receive 没有被调用或没有完成以便跳转处理程序

UDP 服务器:

#include "udp_server.h"


udp_server::udp_server(boost::asio::io_service& io_service, string bind_address, uint16_t bind_port)
    : socket_(io_service)
{
    cout << "udp_server constructor start" << endl;


    boost::shared_ptr<boost::asio::io_service::work> work(
        new boost::asio::io_service::work(io_service));

    for(int x=0; x<5; ++x)
    {
        worker_threads.create_thread(boost::bind(&udp_server::WorkerThread, this , boost::ref(io_service)));
    }

    boost::system::error_code myError;

    boost::asio::ip::address IP;
    IP = boost::asio::ip::address::from_string(bind_address, myError); 

    local_udppoint_.address(IP);
    cout << "IP Address: " << local_udppoint_.address().to_string() << endl;
    local_udppoint_.port(bind_port);
    cout << "Port: " << local_udppoint_.port() << endl;

    socket_.open(local_udppoint_.protocol(), myError);
    std::cout << "Open - " << myError.message() << std::endl;
    socket_.bind( local_udppoint_, myError );
    std::cout << "Bind - " << myError.message() << std::endl;

    udp::endpoint sender_endpoint_;

    struct test *request = (struct test *) malloc (sizeof(struct test));

    socket_.async_receive_from(
        boost::asio::buffer(&request, sizeof(request->type)), sender_endpoint_,
        boost::bind(&udp_server::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));

    cout << "udp_server constructor end" << endl;
}

void udp_server::WorkerThread(io_service &io_service_)
{
    std::cout << "Thread Start\n";
    io_service_.run();
    std::cout << "Thread Finish\n";
}

void udp_server::handle_receive_from(const boost::system::error_code& err, size_t bytes_recvd)
{
    cout << "udp_server::handle_receive_from enters?" << endl;
    if(!err)
    {
        cout << "no message" << endl;
    }
    else
    {
        cout << err.message() << endl;
    }

    if (!err && bytes_recvd > 0)
    {
        cout << "All good" << endl;
    }
    else
    {

        cout << err.message() << "2" << endl;
    }
}

udp_server::~udp_server(void)
{
    //io_service.stop();

    worker_threads.join_all();

    cout << "udp_server::destructor"  << endl;
}

服务器的主要:

#include "udp_server.h"

int main()
{
  try
  {
    boost::asio::io_service io_service;
    //boost::asio::io_service::work work( io_service);
    udp_server s(io_service, "127.0.0.1", 4000);

    //io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  string a;
  cin >> a;
  return 0;

}

UDP 客户端:

#include "udp_client.h"


udp_client::udp_client(boost::asio::io_service& io_service, string send_address, uint16_t send_port)
    : io_service_(io_service), socket_(io_service)
{
    cout << "udp_client::constructor_start" << endl;

    boost::system::error_code myError;

    boost::asio::ip::address IP;
    IP = boost::asio::ip::address::from_string(send_address, myError); 

    remote_endpoint_.address(IP);
    cout << "IP Address: " << remote_endpoint_.address().to_string() << endl;
    remote_endpoint_.port(send_port);
    cout << "Port: " << remote_endpoint_.port() << endl;

    struct test *request = (struct test *) malloc (sizeof(struct test));

    request->type = START_STORAGE;

    socket_.async_send_to(boost::asio::buffer(&request, sizeof(request->type)), remote_endpoint_,
        boost::bind(&udp_client::start_handler, this, boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));

    cout << "udp_client::constructor_end" << endl;
}

void
udp_client::start_handler(const boost::system::error_code&, std::size_t)
{
    cout << "udp_client::start_handler()" << endl;
}

udp_client::~udp_client(void)
{
}

客户的主要:

#include "udp_client.h"

int main(int argc, char* argv[])
{
  try
  {
    boost::asio::io_service io_service;

    udp_client client(io_service, "127.0.0.1", 4000);

    io_service.run ();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  string a;
  cin >> a;
  return 0;
}

正如您在下面的输出中看到的,客户端调用了 async_send_to 并且正在打印处理程序上的消息,但在服务器端没有任何反应

UDP 服务器控制台输出:

udp_server constructor star
Thread Start
Thread Start
Thread Start
Thread Start
Thread Start
IP Address: 127.0.0.1
Port: 4000
Open - The operation completed successfully
Bind - The operation completed successfullyudp_server constructor end
_

UDP 客户端控制台:

udp_client::constructor_start
IP Address: 127.0.0.1
Port: 4000
udp_client::constructor_end
udp_client::start_handler()

知道为什么 async_receive_from 没有完成或调用吗?

【问题讨论】:

  • 顺便说一下,+1 是因为您的问题的格式很好。看到有人以这种方式发帖(发帖)令人耳目一新。

标签: c++ boost udp boost-asio


【解决方案1】:

马上,在析构函数的监听线程上调用 join_all 会导致未定义的行为。您正试图让您的服务器在被破坏的过程中保持运行。不要这样做。例如,从这些线程运行io_service,您有绑定到this* 的处理程序,这些线程将挂接到这些处理程序。在析构函数内部,this* 不再是有效对象。在所有回调中,您应该检查传递的错误参数以查看它是否已设置。

if(error)
{
     std::cout << "Error in MyClass::MyFunc(...): " << error << std::endl;
}

.. 将错误打印到控制台。保证您会从 ::bind 中看到错误,表明某某是无效对象。

您应该在您的服务器主服务器中执行某些操作,以防止主服务器退出。将运行服务器 io_service 和 io_service 本身的线程组移到服务器对象之外。用 ::work() 对象包裹 io_service 以防止 io_service 在它认为它已用完工作时自行停止(不再处理连接)。

除此之外,最简单的做法是将您指向 boost 文档提供的大量 TCP 和 UDP 客户端和服务器示例。 http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/examples.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-24
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多