linux上的boost udp接收器失败了

时间:2014-01-23 16:38:27

标签: boost boost-asio

我将udp单播数据包从windows发送到linux。

我已经使用boost编写了简单的应用程序udp客户端和srever。

我在Linux上运行客户端(udp sender)和Linux上的服务器(udp接收器)。

我的客户端正在发送udp数据包,但我在linux上的udp接收器没有收到数据包。但我可以看到wireshark上的udp数据包(它在我的linux上运行)。

我测试了端口和ipaddress,都是正确的。

下面是在linux上运行的代码。

如果我在Windows上同时运行(客户端和服务器),它可以正常运行

using boost::asio::ip::udp;

class udp_server
{
public:
  udp_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 7799))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {

      start_receive();
    }
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

int main()
{
  try
  {
    boost::asio::io_service io_service;
    udp_server server(io_service);
    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

return 0;
}

1 个答案:

答案 0 :(得分:2)

UDP是一种数据报协议。该协议是无状态的,数据包需要作为单个数据包接收。

有关背景信息,请参阅Beej's Guide to Networking

然而,您的接收缓冲区是1个字节。你不能期望读取超过第一个字节。

这似乎可以从例如tutorial 6 listing。不同的是,这是一个日常服务,它不关心请求关注。所有它想知道的是“收到一个数据包”,它只会无条件地发送白天响应。

因此,解决方案似乎是增加缓冲区大小。如果无法预测/不限制包的大小,请考虑切换到流套接字(TCP / IP)。

这里,作为奖励,使用c ++ 11风格:

#include <boost/asio.hpp>

using boost::asio::ip::udp;

class udp_server
{
    public:
        udp_server(boost::asio::io_service& io_service)
            : socket_(io_service, udp::endpoint(udp::v4(), 7799))
        {
            start_receive();
        }

    private:
        void start_receive()
        {
            socket_.async_receive_from(
                boost::asio::buffer(recv_buffer_), remote_endpoint_,
                [this](boost::system::error_code ec, std::size_t bytes_transferred)
                {
                    if (!ec && (bytes_transferred > 0))
                    {
                        std::cout << "PACKET[" << std::string(&recv_buffer_[0], &recv_buffer_[0]+bytes_transferred) << "]\n";
                    } else
                        throw ec; // TODO
                    start_receive();
                });
        }

        udp::socket socket_;
        char recv_buffer_[1024];
        udp::endpoint remote_endpoint_;
};

int main()
{
    std::cout << std::unitbuf;
    try
    {
        boost::asio::io_service io_service;
        udp_server server(io_service);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}