私たちのアプリケーションでは、Boost ライブラリ (およびネットワーク通信用の ASIO) を使用しています。
最近、同じソケットを介して異なるスレッドからデータを送信している場合、クライアント アプリケーションがガベージ データを受信していることを発見しました。
問題を強調するための小さなテスト:
#include <stdio.h>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
void send_routine(boost::shared_ptr<boost::asio::ip::tcp::socket> s, char c)
{
std::vector<char> data(15000, c);
data.push_back('\n');
for (int i=0; i<1000; i++)
boost::asio::write(*s, boost::asio::buffer(&data[0], data.size()));
}
int main()
{
using namespace boost::asio;
using namespace boost::asio::ip;
try {
io_service io_service;
io_service::work work(io_service);
const char* host = "localhost";
const char* service_name = "18000";
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), host, service_name);
tcp::resolver::iterator iterator = resolver.resolve(query);
auto socket = boost::shared_ptr<tcp::socket>(new tcp::socket(io_service));
socket->connect(*iterator);
boost::thread t1(send_routine, socket, 'A');
boost::thread t2(send_routine, socket, 'B');
boost::thread t3(send_routine, socket, 'C');
t1.join();
t2.join();
t3.join();
}
catch (std::exception& e) {
printf("FAIL: %s\n", e.what());
}
return 0;
}
そこで、ここにソケットを作成localhost:18000
し、ソケットに書き込みを行う 3 つのスレッドに接続して開始します。
別のターミナル ウィンドウで、 を実行しますnc -l -p 18000 | tee out.txt | sort | uniq | wc -l
。出力として期待3
していますが、ネットワーク ストリームで 100 を超える「異なる文字列」が返されます (そのため、データが破損しています)。ただし、バッファ サイズが小さい場合は機能します (たとえば、 に変更15000
する80
場合)。
質問は、ASIO ライブラリの正しい動作ですか? そしてもう1つ:それを修正する方法は?mutex
関数内で使用する必要send_routine
がありますか (または別の解決策があります)?