0

このプログラムが失敗する理由が見つかりません。それは私のブースト使用に違いありません。問題はコメントで強調表示され、一部の関数呼び出しに関する小さなメモがあります

/* 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()、バッファに提供される基になるメモリがハンドラが呼び出されるまで有効なままでなければならないという要件に違反しています。

buffers オブジェクトは必要に応じてコピーできますが、基になるメモリ ブロックの所有権は呼び出し元によって保持されます。呼び出し元は、ハンドラーが呼び出されるまでそれらが有効であることを保証する必要があります。

この基準を満たすには、自動変数ではなくMsgのデータ メンバーを作成することを検討してください。UDP_Server

また、考慮すべき他の2つのポイント:

  • UDP_Server::rbufデータを読み取ることができるメモリがないため、常にゼロのサイズを維持し、何も読み取らないようにします udp::socket::async_receive_from()。バッファとして提供されたメモリ ブロックの内容のみを変更します。メモリ ブロックを既に割り当てているのは、呼び出し元の責任です。すべての着信データグラムを処理するのに十分な大きさにサイズ変更するか、バッファーを遅延して割り当てます。UDP_Server::Listen()udp::socket::async_receive_from()rbuf
  • ではmain()、実際に受信したデータの量に関係なく、 rbuf.size()常に を返します。の戻り値は、受信したバイト数を示します。この値は、 を作成するときと に書き込むときに使用する必要があります。128udp::socket::receive_from()boost::asio::bufferstd::cout
于 2013-10-31T02:32:03.590 に答える