запись в boost ::asio-сокет из разных потоков

В нашем приложении мы используем библиотеки 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? И еще :как исправить? Должен ли я использовать mutexвнутри моей функции send_routine(или есть другое решение )?

5
задан qehgt 20 July 2012 в 15:27
поделиться