异步UDP客户端/服务器通信(BOOST) - 服务器无法读取

时间:2015-04-19 19:54:54

标签: c++ boost udp boost-asio

您好我一直在尝试实现一个简单的服务器/客户端应用程序通过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 个答案:

答案 0 :(得分:0)

马上,在析构函数中的侦听线程上调用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在认为它已停止工作时停止运行(不再需要处理连接)。

除此之外,最简单的方法是指向成熟的TCP和UDP客户端以及提升文档提供的服务器示例。 http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/examples.html