1

まず最初に、私は C++ の初心者であり、Java や C# などの言語の経験はある程度ありますが、一般的にブーストしていることを述べたいと思います。

そうは言っても、Boost TCP ソケットを介してデータを転送するときに問題が発生しています。私はこのコードを使用しています:

送信するには:

tcp::socket s(io_service);
        boost::asio::connect(s, iterator);
        string response = static_cast<ostringstream*>( &(ostringstream() << arg1) )->str() 
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg2) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg3) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg4) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg5) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg6) )->str();

        //pad the rest
        while (response.length() < max_length)
        {
            response += ' ';
        }
        boost::asio::write(s, boost::asio::buffer(response, sizeof(response))); 

読むには:

tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
    while(true)
    {
        socket_ptr sock(new tcp::socket(io_service));
        a.accept(*sock);
        boost::thread t(boost::bind(session, sock));
    }
...
void session(socket_ptr sock)
{
    char data[max_length];
    size_t length;
    try
    {
        while(true)
        {           
            boost::system::error_code error;
            //size_t length = sock->read_some(boost::asio::buffer(data), error);
            length = boost::asio::read(*sock, boost::asio::buffer(data, sizeof data));
            std::cout << "Length " << length << endl;
            if (error == boost::asio::error::eof)
            {
                break; // Connection closed cleanly by peer.
            }
            else if (error)
            {
                throw boost::system::system_error(error); // Some other error.
            }

        }
    }
    catch (std::exception& e)
    {
        std::cout << data << endl;  
        string message = e.what();
        if(std::string::npos != message.find(END_OF_FILE))
        {
            domeSomethingWithTheData(data); 
            memset(data, 0, sizeof data);
        }
        else
        {
            std::cout << data <<endl;
            std::cerr << "Exception in thread: " << e.what() << "\n";
        }
    }
}

私が理解できないのは、使用するものに関係なく ( または のいずれboost::asio::readsock->read_some)、32 文字を超えるデータを取得することは決してないということです。バッファのサイズを に増やしてみまし2048たが、問題は解決しません。

バッファには常に 32 文字を超える文字が含まれています (そのほとんどはガベージです) が、これらは実際にはクライアントから送信されたものではなく、std::cout << "Length " << length32 が出力されるため、サーバー側のバッファの実際の割り当てからのものであると想定しています。

クライアントからサーバーに任意の量の文字を送信する方法についての情報をいただければ幸いです。

編集:

Rafal Rawicki によって提供されたポインターの後、次のコードを使用しています。

 boost::asio::streambuf buffer;
    boost::asio::read_until(*sock, buffer, '\n');
    std::istream is(&buffer);
    std::string line;
    std::getline(is, line); 
    std::cout << line << std::endl;

最後に を追加するという唯一の例外を除いて、クライアント側は変更されていません\n。ただし、これにより多くのEnd of file例外が発生します。

4

2 に答える 2

3

これは実際にはあなたの質問に対する答えではありません。しかし、簡単なアドバイスです。

あなたの文字列連結コードは残酷です!

string response = static_cast<ostringstream*>( &(ostringstream() << arg1) )->str() 
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg2) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg3) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg4) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg5) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg6) )->str();

new を作成する引数ごとostringstreamに値を書き込み、不必要に逆参照してから、不必要にそれすでに持っている型にキャストします。最後に、文字列連結を使用して最終的な文字列を作成します。

この種の文字列連結は効率的ではなく、洗練されたものでもありません (一時オブジェクトや無駄な割り当てなどが必要です)。

ostringstreamは、文字列の連結と書式設定に適したツールであり、効率的で洗練されています。

簡単に言うと、コードは次のようになります。

ostringstream oss;
oss << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << "," << arg5 << "," << arg6;
string response = oss.str();
于 2012-05-23T20:56:34.660 に答える
2

boost::asio::readバッファがいっぱいになるか、エラーが発生するまでデータを読み取る必要があります。

boost::asio::socket::read_someソケットからいくつかのデータを読み取ることになっています。

必要な量のデータを読み取るには、次のことができます。

  • 試したようにboost::asio::readを使用してください。
  • これらの関数を複数回呼び出して、より多くのデータを読み取る
  • read_until予想される区切り文字までデータを読み取るために使用します
  • バイト数などboost::asio::readの引数として受け取るこのオーバーロードを使用します。completion_condition

また、Boost.Asio を使用した同期操作の問題を確認し、代わりに非同期操作の使用を検討してください。

編集: クライアント コードで不適切なバッファの初期化を見逃しました。の使い方boost::asio::readは正解でした。

そのようなバッファを初期化することはできません:

boost::asio::buffer(response, sizeof(response));

文字列全体ではなく、構造体sizeofのサイズを返すためです。std::string私のマシンでは常に 8 です。次を使用します。

boost::asio::buffer(response);
于 2012-05-23T19:12:55.003 に答える