0

私はストリーミング プロトコルを使用してサーバーを作成しているので、ヘッダーの末尾を見つけてコピーし、ブースト バッファー内の他の内容を解析する必要があります。文字列を操作するための最良の方法(文字列を検索する、イテレータを使用してコピー/削除するなど)を見つけたので、std::stringです。しかし、私はchar配列バッファを使用しています。したがって、char 配列と std::string の 2 つのバッファーが必要です。バッファーを操作する必要があるたびに、char 配列を std::string に変換し、処理を行ってから元に戻す必要があります。 std::string.c_str() を使用して char 配列に変換します。私が見つけた別の方法は、streambuf を使用して (前の質問で尋ねたように)、それにistream /ostream を作成し、そこからコンテンツを std::string に入力することです (ドキュメントに示されているように)。streambuf が必要です:
streambuf
mutable_buffers_type
istream
ostream
と std::string
しかし、char 配列と std::string を使用すると、必要なのは :
char 配列
std::string

したがって、streambuf の使用はメモリの無駄だと思います (接続ごとにバッファを作成する必要があります)。std::string をブースト バッファーとして使用できますか? ただし、これを行うためのより良い方法があるかもしれないと思います。アドバイスをいただけますか?

編集:

バッファでこのようなことをする必要がありますが、char 配列は std::string (消去、substr など) のような機能を提供しないため、std::string をバッファとして使用する必要があります。boost::buffer として使用する最良の方法は何ですか、またはこのコードのように解析する最良の方法は何ですか?

#include <iostream>

int main(int argc, char* argv[])
{

    //"header" is header
    //"end" is marking that this point is end of header
    //"data" is data after header
    //this all is sent in one packet which I receive to buffer
    //I need to fill "headerend" to std::string header and then remove "headerend" from begining of buffer
    //then continue parsing "data" which stay in buffer

    std::string buffer = "headerenddata"; //I receive something like this
    std::string header; //here I'll fill header (including mark of end of header)

    //find end of header and include also mark of end of header which is "end" (+3)
    int endOfHeader = int(buffer.find("end"))+3; 

    //fill header from buffer to string header
    header = buffer.substr(0, endOfHeader);

    //delete header from input buffer and keep data in it for next parsing
    buffer.erase(buffer.begin(), buffer.begin()+endOfHeader); 
    //will be just "data" becouse header and mark of header are removed
    std::cout << buffer << std::endl; 
    //will be "headerend" which is "header" and mark end of header which is "end"
    std::cout << header << std::endl;


    return 0;
}
4

1 に答える 1

3

std::stringを作成するためのパラメータとして使用できますboost::asio::buffer。ただし、通常はcharベクトル(std::vector<char>)を使用します。処理する方が簡単だと思いますが、それはコードの残りの部分がどのように設計されているかに本当に依存するかもしれません。

C++11配列を使用することもできます。ベクトルと同様に動作しますが、スペースを静的に割り当てます(つまり、配列が作成されると、基になるバッファーのサイズは変更できません)。これにより、状況によってはパフォーマンスが向上する場合があります。C ++ 11を使用できない場合、Boostには非常によく似たクラスも含まれています。

boost::asio::buffer通常のchar配列(char buf[SIZE])も受け入れますが、可能であれば、前述のオプションを使用する方が便利な場合があります。

参考までに、ここにのドキュメントがありますboost::asio::buffer

更新:char[]からへの変換を回避するために、バッファーの受信と処理の両方にstring使用できます(バッファーの受信にを使用することも機能する可能性がありますが、私はそれを試したことがありません)。vectorstring

だから、受け取るためにあなたはすることができます:

vector<char> msg(N);
...
asio::read(socket, asio::buffer(msg), asio::transfer_at_least(N), ec);

次に、パケットを処理し、ヘッダーとデータを分割するために、イテレーターを使用して、コード(substrおよびerase)でO(n)の複雑さを伴う操作を回避できます。もちろんfind(またはsearch私の例では)避けることはできません:

string end_marker = "end";
auto it = search(msg.begin(), msg.end(), end_marker.begin(), end_marker.end());

process_header(msg.begin(), it + 2);
process_data(it + 3, msg.end());
于 2012-05-27T18:14:20.037 に答える