1

Есть одна программа, которая получает данные с gps приемника по протоколу NMEA. Далее она парсит эти данные и делает уже последующую обработку. Так сложились обстоятельства, что данного приемника больше нет, а программу дописать очень хочется. Я придумал решение. Создал другую программу, которая генерирует эти самые nmea-sentences. Программа-генератор создает строку std::string в стиле протокола каждые n секунд. Задержка осуществляется с помощью std::this_thread::sleep_for(n);

Вопрос состоит в следующем: Как я могу передавать эти данные в реальном времени в свою первую программу. (пробовал пайпы, но там проблема в том, что я передаю бесконечным циклом данные, а вторая программа может их считать, только когда я прекращаю запись первой программой).

Дополнение

Для примера привожу программу записи в файл:

// в данном случае использую текстовый файл, 
// чтобы нормально отслеживать порядок событий
int main() {
std::string path = "pipe/PipeGSVsentence.txt";
std::ofstream file(path);

if (file.is_open()) { for (size_t i = 0; i < 50; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); file << i << " HELLO WORLD %1 \n"; file.flush(); } file.close(); } else { std::cout << "Не удалось открыть файл." << std::endl; } return 0; }

Вопрос такой: Как правильно читать файл, чтобы в консоль выводились новые строки в момент записи в файл другой программой? Пробовал что-то подобное:

int main() {

std::string path = "pipe/PipeGSVsentence.txt";

std::ifstream file; file.open(path); if (file.is_open()) { std::string line; while (true) { while (std::getline(file, line)) { std::cout << "Прочитано: " << line << std::endl; } std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } file.close(); } else { std::cout << "Не удалось открыть файл." << std::endl; } return 0; }

В данной ситуации программа читает пару строк и зависает в бесконечном цикле.

Придумал вариант: в программе, записывающей строки, реализовать такой цикл:

  1. открыть файл
  2. записать строку
  3. закрыть файл

в программе читателе следующий цикл:

  1. открыть файл
  2. прочитать строки
  3. закрыть файл

Но мне кажется есть что-то поэффективнее, до чего я не могу додуматься и не могу найти. Да и плюсом, если использовать pipe, то одна из программ в какой-то момент завершится по причине SIGPIPE

kreppid
  • 13
  • вот посмотрите сейчас на правую часть страницы. там приведены ссылки на похожие вопросы. например, Передача и приём данных между процессами. ну а вообще можно начать с википедии – aleksandr barakin Oct 25 '23 at 11:18
  • Странная проблема с пайпом, вероятно из-за буферизации вывода в потоке генератора. Пишите туда write-ом сразу весь nmea-sentence, никаких задержек (существенных) возникать не должно. – avp Oct 25 '23 at 18:18
  • Я так и делал, отправлял сразу одну строку с интервалом 2-3 секунды. Но программа reader не успевала читать. Даже проводил тесты, когда вместо бесконечного цикла делал конечный. Тогда программа читатель читала информацию только после завершения цикла в программе writer. – kreppid Oct 26 '23 at 06:38
  • @kreppid, может быть вам проще через UDP/IP передавать и это больше будет похоже на реальное применение, тем более, что когда переходят от портов к ethernet обычно выбирают именно UDP/IP – Pavel Gridin Oct 27 '23 at 08:30
  • @PavelGridin Хороший вариант, но я еще не имею столько знаний в сетевом программировании. Я дополнил вопрос, может быть вы знаете решение) – kreppid Oct 27 '23 at 11:17
  • @kreppid, вам явно предпочтителен асинхронный ipc, а вы пытаетесь приспособить синхронный. – Pavel Gridin Oct 27 '23 at 11:28
  • @PavelGridin, вы случайно не ведаете литературой/форумами с теорией по ipc? достойного ничего не могу найти на просторах интернета. Везде всё кусочными отрывками и без связей( – kreppid Oct 28 '23 at 15:32
  • @kreppid, нет такого специального не знаю, но это очень широкая тема, как программирование, вот на таких форумах и обсуждают, вот вам ещё хороший вариант для начинающих: https://www.sfml-dev.org/documentation/2.6.0/classsf_1_1UdpSocket.php, с примером – Pavel Gridin Oct 29 '23 at 06:40

1 Answers1

2

Раз ваша программа получает данные с аппаратного устройства, то она должна делать это через какой-то аппаратный интерфейс. Обычно это COM-порт. Существует возможность создать два виртуальных закольцованных порта так, что при отправке данных на один порт они будут появляться на втором. Таким образом, можно симулировать наличие аппаратного устройства.

Для создания таких портов существуют специальные драйверы. Например, для windows это com0com, для linux - tty0tty. Для macos поищите по запросу Virtual null modem emulator.

Любые другие способы ведут к необходимости менять процедуру обмена данными с аппаратным устройством, здесь же приём и передача останутся без изменений.

maestro
  • 4,735
  • Спасибо, я рассмотрю Ваше предложение про виртуальный последовательный порт. Однако мне не принципиально каким способом передавать данные, это не главное в моей задаче. Поэтому интересно разобраться как можно еще обмениваться данными между приложениями с моими условиями. – kreppid Oct 25 '23 at 16:23
  • Есть nmea симуляторы, которые могут выдавать разные сообщения на реальный или виртуальный порт, причем имитировать время, движение, точность и прочее. Чтобы всё было по настоящему я бы гнал nmea с симулятора в программу через аппаратные com-порты – Pavel Gridin Oct 26 '23 at 08:36
  • @PavelGridin, спасибо за совет. Не задумывался, что такое уже придумали. Но всё таки, чем дольше я копаюсь в проблеме ipc, тем больше вопросов появляется) – kreppid Oct 26 '23 at 18:29
  • @kreppid, есть прекрасная вещь - очередь для многозадачных применений из пакета Intel TBB, класс называется tbb::concurrent_bounded_queue, я через неё гоню кадры из видеокамеры из одного процесса в другой – Pavel Gridin Oct 27 '23 at 08:11
  • @kreppid, хотя то что я написал, для внутрипрограммного применения, т.е. между потоками – Pavel Gridin Oct 27 '23 at 08:27