Boost异步服务器类:调试断言失败和空缓冲区

时间:2013-10-31 01:17:49

标签: c++ boost boost-asio

无法找到此程序失败的原因。一定是我的提升用法。问题在评论中突出显示,并且有一些关于某些函数调用的小注释

/* Includes Hidden */
using boost::asio::ip::udp;


class UDP_Server {

public:
    UDP_Server(boost::asio::io_service& IO, unsigned short PORT) 
        : sock(IO, udp::endpoint(udp::v4(),PORT)) {
        Listen();
    }
    ~UDP_Server() {
        for(auto& endpoint : Clients) {
            delete endpoint;
        }
        Clients.clear();
    }


    void Listen() {
        //waits for msg to be sent.  Captures end point and sends address
        //so server can store connections

        udp::endpoint* T = new udp::endpoint;
        sock.async_receive_from(
            boost::asio::buffer(rbuf),*T, 
            boost::bind(&UDP_Server::handle_rec, this, T, 
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }

    void handle_rec(udp::endpoint* EP, const boost::system::error_code& err, size_t len) {
//When the program enters here, err is 234 (windows error for more data available)
//len is 0 and rbuf is empty.

        if(err && err != boost::asio::error::message_size) {
            std::cerr << err.message() << std::endl;
        }

        std::cout.write(rbuf.data(),rbuf.size());

        bool ThisClient = false;
        std::string Msg = "";

        for( auto& EPs : Clients) {

            if(EPs == EP) {
                ThisClient = true; break; 
            }       
        }

        if(!ThisClient) {
            if(len > 0 && rbuf[0]=='0') {
                Clients.push_back(EP);
                Msg = "Connected";
            }else{
                Msg = "Connection Refused";
            }   
        }else{
            if(rbuf[0]=='0') {
                delete EP;
                Clients.remove(EP);
                Msg = "Disconnected";
            }
        }
        //queue message to send back and call  handle_snd function
        sock.async_send_to(boost::asio::buffer(Msg),*EP,
            boost::bind(&UDP_Server::handle_snd,this,EP,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
            ));

        Listen(); //listen for some more messages!
    } //debugging through the first time through this function eventually exits here
//and ends up going through a bunch of code I didn't write, and ultimately fail.

    void handle_snd(udp::endpoint *Dest, const boost::system::error_code& err, size_t len) {

    }

private:
    udp::socket sock;
    std::list<udp::endpoint*> Clients;
    std::vector<char> rbuf;
};

void HostStart() {
    try {
        boost::asio::io_service io;
        UDP_Server Host(io,13);
        io.run();
    }catch(std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}

int main() {


    std::thread thd(HostStart); //start server

    try {
        boost::asio::io_service io2;
        udp::resolver res(io2);
        udp::resolver::query queer(udp::v4(),"127.0.0.1","daytime");
        udp::endpoint HostEP = *res.resolve(queer);
        udp::socket sock(io2);
        sock.open(udp::v4());


        std::string Msg = "0";
        std::vector<char> MsgArray(Msg.begin(),Msg.end());

        sock.send_to(boost::asio::buffer(Msg),HostEP);

        io2.run();
        udp::endpoint RecEP;
        std::array<char,128> rbuf;

        sock.receive_from(boost::asio::buffer(rbuf),RecEP);
        std::cout.write(rbuf.data(),rbuf.size());

        sock.send_to(boost::asio::buffer(Msg),HostEP);
        sock.receive_from(boost::asio::buffer(rbuf),RecEP);
        std::cout.write(rbuf.data(),rbuf.size());

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

    Sleep(10000);
    return 0;
}

如果我使用调试并浏览此代码,我发现我最终会在一个名为的文件中结束 win_iocp_io_service.ipp 我收到此错误: Error

在我的主要内容中,我只是尝试同步发送一条消息来测试异步服务器类。我不知道为什么在异步服务器调用之后缓冲区为空以及为什么我收到此错误。

可能与我在io服务上调用run以及我尝试多线程的方式有关。

谢谢

1 个答案:

答案 0 :(得分:1)

这可能是程序调用未定义行为的结果。在UDP_Server::handle_rec()内,对udp::socket::async_send_to()的调用违反了在调用处理程序之前提供给缓冲区的底层内存必须保持有效的要求。

  

尽管可以根据需要复制buffers对象,但调用者仍保留底层内存块的所有权,这必须保证它们在调用处理程序之前保持有效。

要符合此条件,请考虑将Msg设为UDP_Server的数据成员,而不是自动变量。

另外,还有两点需要考虑:

  • UDP_Server::rbuf将始终保持大小为零,导致udp::socket::async_receive_from()中的UDP_Server::Listen()无法读取任何内容,因为没有可以读取数据的内存。 udp::socket::async_receive_from()仅修改作为缓冲区提供给它的内存块的内容;调用者有责任分配内存块。将rbuf的大小调整为足以处理所有传入数据报的大小,或lazily allocate缓冲区。
  • main()中,rbuf.size()将始终返回128,无论实际收到多少数据。 udp::socket::receive_from()的返回值表示接收的字节数,在创建boost::asio::buffer和写入std::cout时应使用此值。