0

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

/* 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 的文件,并且会收到以下错误: 错误

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

可能与我在 io 服务上调用 run 的时间以及我尝试对其进行多线程处理的方式有关。

谢谢

4

1 回答 1

1

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

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

要满足此标准,请考虑创建Msg的数据成员UDP_Server,而不是自动变量。

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

  • UDP_Server::rbuf将始终保持大小为零,导致udp::socket::async_receive_from()inUDP_Server::Listen()什么也不读取,因为没有可以读取数据的内存。 udp::socket::async_receive_from()只修改作为缓冲区提供给它的内存块的内容;调用者有责任分配内存块。要么调整大小rbuf到足以处理所有传入数据报的大小,要么延迟分配缓冲区。
  • main(),rbuf.size()将始终返回128,无论实际接收到多少数据。 的返回值表示接收到的字节数,在创建和写入udp::socket::receive_from()时应使用此值。boost::asio::bufferstd::cout
于 2013-10-31T02:32:03.590 回答