簡體   English   中英

C ++ Boost Asio | 同步寫入到異步讀取| 第二次讀取無法接收正確的數據

[英]c++ boost asio | sync write to async read | unable to receive correct data in 2nd read

介紹:

我正在嘗試使用c ++和boost :: asio制作服務器/客戶端應用程序,我還試圖通過連續的異步讀取使另一端收到的同步寫入。 例如,我的服務器異步讀取固定字節長度的數據流,然后移至客戶端從同步寫入發送的下一個字節。

問題:

在連續異步讀取中,第一個流字節被正確讀取,但是當它繼續進行下一個異步讀取時,我期望從另一端以相同的字節長度發送一些內容,但這是垃圾,或者無法將其轉換為有價值的數據。

編碼:

    private:
      static const int MAX_MTU = 1500;  //Ethernet Maximum Transfer UNIT (MTU)...
      static const int TRASH_CAN = 100; //Amount to substract from the MAX_MTU to make room for basic packet structure elements.
      static const int BUFFER_SIZE = MAX_MTU - TRASH_CAN;
      boost::mutex mutex;
      typedef char* data_bytes;
      std::list<data_bytes> data;

    private:
      tcp::socket socket_;
      boost::asio::io_service& io_service_;
      moqane::tcp_packet *packet_;

    // CTOR for the incoming connection from a client to the server
    public: tcp_session(boost::asio::io_service& io_service)
      : io_service_(io_service),
        socket_(io_service),
        packet_(new moqane::tcp_packet())
    {
        // ......
    }

    // CTOR for the outgoing clinet connection to the server...
    public: tcp_session(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator)
      : io_service_(io_service),
        socket_(io_service),
        packet_(new moqane::tcp_packet())
    {
        boost::asio::async_connect(socket_,
                                   endpoint_iterator,
                                   boost::bind(&tcp_session::connect_to_server_hndlr,
                                               this,
                                               boost::asio::placeholders::error)
                                   );
    }

    tcp::socket& socket()
    {
        return socket_;
    }

    public:
    void read_header()
    {

        read_packet(packet_->HEADER_LENGTH,
                    boost::bind(
                            &moqane::tcp_session::read_header_hndlr,
                            shared_from_this(),
                            packet_->HEADER_LENGTH,
                            boost::asio::placeholders::error)
                    );
    }

    private:
    void connect_to_server_hndlr(const boost::system::error_code& error)
    {
        if (!error)
        {
            read_header();
        }
        else
        {
            // TODO: fire the error event...
        }
    }

    private:
    template <class T>
    void read_packet(int packet_length, T handler)
    {
        /*
        Packet Structure: (Mohamed Tarek (moqane))
        ==============================================================================================
        HEADER: could be a 3 or 4 bytes that give enough information to the endpoint on how to receive
                those bytes.
        SIZE  : A 4 byte-length number that tell the endpoint how much data in bytes ar comming.
                ex: 0340 which should tell us that the incoming data are 340 bytes, so we will not
                receive more or less than that.
        DATA  : the incoming valuable information that we want to receive in the first place.

        ---------------------------------------------
        |        |      |                            |
        | HEADER | SIZE | DATA...                    | ----> PACKET
        |   3b   |  4b  | N/A b                      |
        ----------------------------------------------
        ==============================================================================================
        */

        if (data.size() > 0)
        {
            data.clear();
        }

        char d[moqane::tcp_session::BUFFER_SIZE];
        data.push_back(d);
        boost::asio::async_read(socket_,
                                boost::asio::buffer(data.back(), packet_length),
                                handler
                                );
    }

    private:
    void write_packet(char* data_bytes)
    {
        boost::asio::write(socket_, boost::asio::buffer(data_bytes, sizeof(data_bytes)));

    }

    private:
    void write_packet_hndlr(const boost::system::error_code& error)
    {
        if (!error)
        {
        }
        else
        {
        }
    }


    private:
    void read_header_hndlr(int packet_length, const boost::system::error_code& error)
    {
        if (!error)
        {
            // convert bytes to wxstring
            // wxString s = moqane::wx2string::To_wxString(packet_->DATA(), packet_->HEADER_LENGTH());

            // convert our bytes to string
            std::string header(data.back(), packet_length);

            if (packet_->is_header(header))
            {
                // read the SIZE packet
                read_packet(packet_->SIZE_LENGTH,
                            boost::bind(
                                    &moqane::tcp_session::read_size_hndlr,
                                    shared_from_this(),
                                    packet_->SIZE_LENGTH,
                                    header,
                                    "",
                                    boost::asio::placeholders::error)
                            );
            }
            else
            {
                // reread the HEADER packet if it's not a valid header
                read_header();
            }
        }

        else
        {
            // TODO: fire the error event...
        }



    }

    private:
    void read_size_hndlr(int packet_length, std::string header, std::string info, const boost::system::error_code& error)
    {
        if (!error)
        {
            std::string str_length(data.back(), packet_length);

            int next_packet_length = moqane::number2string::ToInt(str_length);

            if (next_packet_length > 0)
            {
                if (header == packet_->HEADER_STRING)
                {
                    read_packet(next_packet_length,
                                boost::bind(
                                        &moqane::tcp_session::read_STRING_hndlr,
                                        shared_from_this(),
                                        next_packet_length,
                                        boost::asio::placeholders::error)
                                );
                }
                else if (header == packet_->HEADER_COMMAND)
                {

                }
                else
                {
                    // reread the HEADER packet if it's not a valid header
                    read_header();
                }
            }
            else
            {
                // reread the HEADER packet if it's not a valid size
                read_header();
            }
        }
        else
        {
            // TODO: fire the error event...
        }
    }

    private:
    void read_STRING_hndlr(int packet_length, const boost::system::error_code& error)
    {
        std::string std_str(data.back(), packet_length);
        std::string v = "";
    }

    public:
    void write_STRING(char* string_data)
    {
        boost::mutex::scoped_lock lock(mutex);
        {
            write_packet(moqane::number2string::To_CharArray("STR"));
            write_packet(moqane::number2string::To_CharArray("xxx1"));
            write_packet(moqane::number2string::To_CharArray("a"));
        }
    }

};

我懷疑問題出在read_packet

    char d[moqane::tcp_session::BUFFER_SIZE];
    data.push_back(d);
    boost::asio::async_read(socket_,
                            boost::asio::buffer(data.back(), packet_length),
                            handler
                            );

這是在局部變量中創建緩沖區d。 然后,將指向d的指針推入data ,然后將其用於形成async_read的緩沖區。 然后,您離開該功能。 這將導致數組被破壞,並帶有多個懸空指針,包括async_read。

我建議為標題創建緩沖區,該緩沖區的名稱類似於“ header”,應作為類的一部分。 我不確定您是否也需要單獨的data向量。

現在已解決,主要問題是在發送時構造緩沖區時出現錯誤的packet_length 因為我得到的是sizeof()的長度,根據我的處理器體系結構,該長度總是返回4。 所以我現在使用以下函數獲取char *的長度。

public:
    static int CharArray_Length(char* somedata)
    {
        std::list<char> l;

        while(*somedata != 0)
            l.push_back(*somedata++);

        // If you want to add a terminating NULL character
        // in your list, uncomment the following statement:
        // l.push_back(0);

        return l.size();
    }

參考: https : //stackoverflow.com/a/15034741/1301186

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM