c++ - 异步 UDP 客户端/服务器通信 (BOOST) - 服务器不读取

标签 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 没有完成或没有被调用吗?

最佳答案

马上,在析构函数中的监听线程上调用 join_all 将导致未定义的行为。您试图让您的服务器保持运行,而它正处于被破坏的中间。不要这样做。例如,运行 io_service从这些线程中,您有绑定(bind)到这些线程将挂接到的 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

关于c++ - 异步 UDP 客户端/服务器通信 (BOOST) - 服务器不读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29735086/

相关文章:

在构造函数中使用类成员时的 C++ undefined reference

c++ - 如何在每次达到 30 个字符时拆分字符串

c++ - C++中的动态 boolean 数组

c++ - 此 shared_ptr 示例中的内容不清楚

c - 一定时间后停止 recvfrom()

c++ - C++ unix socket编程,recv返回0,但仍然接收数据,但有时接收的比发送的多

c++ - 将 boost::ptr_vector 添加到双端队列,typeid 不匹配

c++ - 使用 Boost 解析后在 JSON 文件中查找重复项

Java:接收具有多个DatagramSockets的UDP datgram数据包

c++ - 通过 UDP 将信息哈希发送到 Bittorrent Tracker