2011-02-23 8 views
0

async_read_someを使用して_dataというchar []に保存されているポートからデータを読み込みます。そのバッファサイズは、すべての要求のために十分な大きさである:std :: stringが(boost。)内のストレージとして使用すると乱れるasync_read_some

void start() { 

    socket_.async_read_some(boost::asio::buffer(data_,BUFFERSIZE),make_custom_alloc_handler(allocator_,boost::bind(&attentionSession::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); 

} 

void handle_read(const boost::system::error_code& error, size_t bytes_transferred) { 

    string ip = socket_.remote_endpoint().address().to_string(); 
    log->processData(data_,ip,"memory"); 
    strcpy(data_,""); 

} 

PROCESSDATA *別新しくalloced文字にそれをコピーすることによって、要求に(タイムスタンプなどのような)いくつかの追加情報が追加されます。そして、この文字は[]のstdにその、char *を追加するwriteToMemory(のchar *)に送信されます::文字列memoryBuffer:

void writeCacheToFile() { 

    // This function writes buffer data to the log file 

    char* temp = new char[memoryBuffer.length() + 1]; 
    strcpy(temp, memoryBuffer.c_str()); 
    writeToFile(temp); 
    delete[] temp; 
    memoryBuffer.clear(); 

} 

void writeToMemory(char* data) { 

    int maxSize = 1024; 

    // Checks if char* data would 'fit' into the pre-defined maxSize 

    if ((strlen((const char*)data) + memoryBuffer.length()) >= maxSize) { 
     writeCacheToFile(); // If not the cache memoryBuffer is saved first 
    } 

    memoryBuffer.append((const char*) data); 

    cout << memoryBuffer.length() << endl; 

} 

それは動作しますが、リクエスト(要求とそれを砲撃)が常に存在する場合、物事がおかしくアップ。あなたはwriteToMemory()関数の中で上記の見ることができるように私はmemoryBufferの現在の長さをプリントアウトするために行を追加しただろうと私はそれがのstd ::文字列のスレッド安全性に関係する代持っていると思う場所です:

96 
188 
284 
3639 
94 
190 
286 
2591 
102 
198 
294 
388 
484 
2591 
96 
2591 
96 
190 
286 
2591 

(processData()によって処理される)要求の長さは96文字です。しかし、ここではmemoryBufferの長さがちょうど上がったり下がったりします。いくつかの長さはmaxSize(1024文字)よりも大きくなります。

編集:サムはさらにコードを追加する必要があります。

boost::asio::io_service ioService; 
boost::scoped_ptr<boost::thread> ioServiceThread; 
server_class server (ioService,PORT); // Create server instance 
ioServiceThread.reset (new boost::thread (boost::bind (&boost::asio::io_service::run, &ioService ))); 
// Only one threaded io_service (to receive user inputs in main() function) 

そして、これが要求を完了した後async_acceptorの機能である:これは私がio_serviceを起動する方法です

typedef boost::shared_ptr<session_class> session_ptr; 

void handleAccept(session_ptr thisSession, const boost::system::error_code& error) { 
    if (!error) { 
     thisSession->start(); // Calls the start() function above 
     thisSession.reset(new session(ioService,LOGGING_CLASS)); 
     acceptor.async_accept(thisSession->socket(),boost::bind(&server_class::handleAccept, this, thisSession, PLACEHOLDER_ERROR)); 
    } 
} 

session_classは、関数が(スタート保持)とhandle_read(x、y)は、上述しました。 LOGGING_CLASSは、ログファイルを書き込むクラスを提供します(関数writeCacheToFile()とwriteToMemory(char *)を保持します)。ログ(上記)はこのクラスの一種です。

EOE:EDIT OF END

私はブースト::スレッドでそれが完全に混ざっmemoryBuffer

で終わる(STDする::文字列を受け取った、char *を付加する)キャッシュ一部を外部委託修正しようとした場合

本当にstd :: stringsや他の何かのスレッドセーフティですか?

ご協力いただきありがとうございます。 :)

ポール

+0

std :: stringはスレッドセーフであると思いますか? –

+0

このトピックはStackOverflow [リンク](http://stackoverflow.com/questions/1594803/is-stdstring-thead-safe-with-gcc-4-3)にもありますが、g ++ 4.2の有無はわかりません。 1はスレッドセーフなstd :: stringsをサポートしています。 – Paul

+0

現在の標準ではスレッドは言及されていないので、std :: stringはスレッドセーフではありません。あなたは何とか複数のスレッドを使って何をしようとしていますか? –

答えて

1

問題はBoostでもBoost :: Asioでもありませんでした。私が自分のアプリケーションをテストする方法方法であった:

私は、このコマンドを使用してテストファイルが36文字に長いテスト文字列が含まれてい

nc localhost 4450 <testfile 

を自分のアプリケーションのパフォーマンスと機能をテストするために、NC(Netcatを)を使用しました。 Netcatは遅かっただけでなく、この問題の起点でした。

私の戦略を変更し、少しのboost :: asioアプリケーションをコーディングしてから、同じリクエストを自分のアプリケーションに送信した後、それは機能しました。速く、簡単に、問題なく。

私は自分のレッスンを学びました:Netcatを再びストレステストに使用しないでください!

+0

ちょうど好奇心が強い、netcatの問題は何ですか?私の経験では非常に有用なプログラムです。 –

+0

Netcatが転送された文字列を混乱させる。私はポート4450を通常使っていないのに、何とか他のものと混ざってしまった。本当に変だ。しかし、この小さな自己スクリプトアプリケーションで問題なく動作します。 – Paul

0

私はどうしたらまず最初に、あなたがasync_read_someを呼び出す行をリファクタリングです。何が起きているのかを見るのはとても難しいです。

これを打つと、古い呼び出しが戻る前にhandle_readを新たに呼び出すことになります。 handle_readはスレッドセーフではありません。別に何か他のものから、

strcpy(data_,""); 

は、複数のコピーがすべてDATA_にコピーしようとしているとき、あなたにトラブルを与えるために起こっています。

handle_readをスレッドセーフにする必要があります。

+0

それは良く機能しますが、完璧ではありません。ランクを破るいくつかの「長さ」がまだあります。 – Paul

+1

何が良いですか? 「ランクを破る」とはどういう意味ですか? – ravenspoint

+0

maxSize(1024文字)よりもはるかに大きいです。いくつかはそれを2〜3回超えています。 – Paul

1

私はこれと同じ点をコメントとして付けましたが、回答に拡大する価値があると思いました。あなたが持っているコードのスニペットを投稿することは非常に有用ではありません、彼らは私たちに完全な画像を与えていません。たとえば、以下の概念は、私には明らかにされていない:

  1. あなたのasync_read_someハンドラでbytes_transferredパラメータをチェックしていません。これは非常に重要です。nバイトを読むように言っても、の場合、n - xバイトを読むと、canが返されます。 documentation statesとして、async_readfree functionのような合成操作の1つを使用することを検討する必要があります。
  2. example providedに基づいて、非同期読み取り操作にはcustom memory allocationsが使用されています。なぜそれが必要ですか?
  3. バッファ寿命。例:async_readハンドラが呼び出されるまで、バッファはスコープ内に留まりますか?
  4. オブジェクトの有効期間。例:shared_ptrを正しく使用していますか? io_serviceは、そのイベントループ全体のスコープ内にありますか?
  5. あなたはプロセスごとに1つ、またはスレッドごとに1つのio_serviceを使用していますか?
  6. なぜスレッドが必要ですか?通常、単一スレッドのコンテキストで非同期プログラミングを理解する方が簡単です。

これらのすべては、Boost.Asioを使用する際に非常に重要な概念です。デバッグの一部は、認識された問題を小さな再生器に沸騰させることです。これは、Stack Overflowと一般的に良いプログラマになるのに便利です。それはあなたが問題を理解するのに役立ちますし、また私たちはあなたがそれを見つけるのに役立ちます。私たちがコンパイルできるより小さな再現可能な例を作ることに少しでも努力することを強くお勧めします。それが不可能な場合は、単一のスレッド・シナリオが機能していることが証明された後にのみ、複数のスレッドの使用を検討してください。

+0

こんにちはサム、あなたの答えをありがとう。私はポイント1をチェックし、これを自分のコードに適合させました - 良い点です。ポイント2:私がこれをしないと、私のアプリケーションはすべての記憶をまっすぐに食べる。 3:ベスト・ポイント。私はこれについて考えなかった(これは安全だと思ったが、私は間違っていた)。 4:すべてが主な機能()にあります。だから問題ないはずです。 5. main()関数の1つ。スレッディングはありません。 6.残念なことに、私はロギングの部分をスレッド化するという考えを怠ることに失敗しました。ご協力いただきありがとうございます;コードを修正するのに多くの助けをしましたが、主な問題を別の方法で解決しました。 – Paul

関連する問題