Comments 29
На сайте overbyte.eu есть ветка MIDWARE — я использовал изложенные автором идеи для реализации подобного обмена.
Там не требуется создание сервера, отслеживание соединения и все такое. Просто нужно создать майлслот и проверять, не закинул ли туда кто-нибудь чего-нибудь полезное (типа ножки для стола (с) :-)
В целом MailSlot и Pipe это как UDP и TCP сокеты.
Ну и ваш пример весьма показателен для современного мира — любители фреймворков живут исключительно внутри своих фремворков и очень слабо себе представляют возможности и API платформы, под которой они работают. Выход за пределы фреймворка сопровождается острым приступом агаророфобии.
То, что в некоторых случаях эффективнее сделать свою библиотечку (а она получается очень компактной), содержащей UDP и TCP сокеты и TCP сервер для работы в синхроне в отдельном потоке для них просто откровение — люди не представляют что такое WINSOCKS и как с ним работать.
Про ряд интересных функций, которых нет в стандартных заголовках (но они описаны в MSDN и «достаются» через GetProcAddress) уж и говорить не стоит…
Вот это и есть агарофобия — в данном случае паническая боязнь выйти за пределы фреймворка на просторы системного API.
Есть ощущение, что подобное и в других областях наблюдается (та же мобильная разработка — скорее схватить самый модный на текущий момент фреймворк и вперед — к монетизации своего приложения).
Я сам продолжительное время на билдере работал, но начинал еще под досом, с Turbo C 1.0 Б потом 2.0, Turbo C++, Borland C++ — 4-я версия была невозможно глючной, с нее ушел на MSVC и потом уже вернулся на билдер 6-й.
Помню что когда с доса на вин переходил, первое приложение написал на чистом WinAPI. Просто чтобы понимать как оно работает. Ну и в билдере не боялся апишные функции использовать там, где по каким-то причинам VCL не устраивала или ее нехватало.
Что касается межпроцессных и межпоточных коммуникаций, то в последнем виндовом проекте этого было много и пришлось глубоко вникать в эту тему.
Я сам продолжительное время на билдере работал, но начинал еще под досом, с Turbo C 1.0 Б потом 2.0, Turbo C++, Borland C++ — 4-я версия была невозможно глючной, с нее ушел на MSVC и потом уже вернулся на билдер 6-й.
Вот-вот — эта особенность нас, старичков. (Рассыпает песочек...)
В 1990-е у нас Delphi и ее брат-близнец CBuilder были дико популярны. Мне сложно сказать, с чем эта дикая популярность была связана (может, книги по Pascal сюда завозили бесплатно, а за все остальные книги просили денежку), но отсюда берет начало эта распространенность Delphi на нашей территории. Собственно, не будь России, Абракадабра уже давно бы загнулась — в цивилизованных странах ее продукты уже давно нахрен никому не нужны. Одни мы их еще покупаем, вот она, видимо, потому еще шевелится.
Современное же поколение программеров этой Delphi-манией уже не охвачено. Они, полагаю, даже не в курсе, что сей уродец мира программирования существует.
Хотите писать под винду? Учите прежде всего WinAPI и те системные средства, что она предлагает. Ну и просто архитектурные решения, позволяющие понимать когда и где выгоднее использовать асинхрон в общем потоке, а когда и где — синхрон в отдельном потоке.
И уж точно мало кому в голову приходит расширить фреймворк путем дописывания каких-то своих библиотек или функций.
Для себя я как-то пришел к тому, что когда чего-то нехватает, я просто дописываю это сам. А если этот кусок кода из одного проекта вдруг требуется в другом, он оформлаяется в виде библиотеки.
Долго жил под виндами. Писал на С и С++. Потом несколько лет назал в жищни случился крутой поворот и теперь я пишу под AS/400 главным образом на специфическом языке RPG (мало известен за пределами этой платформы, хотя у MS была попытка создать VisualRPG).
Язык специфический, ориентирован прежде всего на работу с БД и коммерческие рассчеты. И там совершенно нет такой вещи как списки. А я очень привык с ними работать. Даже больше, чем со статическими массивами. И очень мне их нехватало. В RPG есть указатели. И есть понятие структуры. Но все это как-то коряво там выглядит.
Но к счастью, С/С++ на этой платформие тоже поддерживается (более того, там есть концепция ILE — интегрированная языковая среда, позволяющая одну программу собирать из нескольких модулей на разных языках). Так что довольно скоро я (для себя в первую очередь, но разработка имела успех и у коллег) сделал сервисную программу (некий аналог виндовой dll) в которой было реализовано несколько алгоритмов на базе списков, которые достаточно легко можно использовать в RPG программах. Да, на это было потраченотнекоторое количество личного времени, но сейчас все это сильно упрощает разработку.
Потребуется что-то еще — будет что-то еще. Не проблема.
Да, «разработчик C++» действительно вылазит, но объемы всё равно не сравнимы с «Full stack developer». А так много чего вылазит: Go, Rust, Java…
Глянул я на эти мэйл-слоты нынче, и не вижу чем они проще и удобнее труб. И зачем в этой задаче негарантированность доставки и броадкаст?..
Есть принципиальная разница между слотом и трубой. Труба - потоковый канал, слот - датаграммный.
Представьте, что у некоего процесса есть канал для приема данных от других процессов. И в него 3-5 процессов постоянно что-то посылают. В случае трубы у вас буте сплошной поток байт и вам придется самому разбирать где начало очередного сообщения, где его конец и начало нового. Т.е. есть у вас в канале 5 сообщений по 10, 40, 30 и 50 байт соответсвенно. Вы читаете из канала 100 байт. В эти 100 байт попадет первое, второе, третье и первые 20 байт четвертого сообщения. А дальше вам надо разгребать что где. Это труба.
Со слотом все иначе. Там атомом является все сообщение целиком. В том же самом случае (сообщения в канале 10, 40, 30 и 50 байт) читаем 100 байт - оно в первый раз прочитает первое сообщение - 10 байт. Второй раз - второе сообщение 40 байт, в третий раз 30 байт, в четвертый - 50. И вам не надо разбираться где что.
На CreateNamedPipeW - Win32 apps | Microsoft Learn откройте для себя режимы PIPE_TYPE_MESSAGE и PIPE_READMODE_MESSAGE
Ну я, слава богу, под винду уже 8 лет как не пишу. Так, по старой памяти...
А там, подо что пишу, есть UNIX Sockets и очереди данных (UserQueue и DataQueue). Которые намного удобнее пайпов. Во-первых, это системные объекты, которые не привязаны к конкретному процессу и сохраняются даже когда нет процессов их использующих, во вторых, там возможно к каждому сообщению добавлять "ключ" который может использоваться для извлечения сообщения из очереди (например, имя процесса, для которого это сообщение предназначено). В третьих, очередь всегда позволяет посмотреть содержимое, не удаляя его (peek). Или просто узнать сколько в ней сейчас сообщений.
Ну, посмотреть не удаляя пайпы тож дают, есть функция PeekNamedPipe
Эээ, пытаться сортировать в стринглисте
Да вы батенька извращенец
С многопоточностью и межпоточной коммуникацией работал много. Как под Win раньше, так и под AS/400 сейчас.
Непонятно в чем сложность
реализация механизма передачи файла на основе первого варианта сервера (Multithreaded Pipe Server) оказывается слишком сложной.
Наиболее простой на мой взгляд подход. Правда, скажу сразу — с пайпами не работал — немного пробовал, не понравилось (под мои задачи). Под Win использовал MailSlots и сокеты (как TCP, так и UDP). Под AS/400 богаче выбор — UnixSockets, socketpair, DataQueue, UserQueue.
Наиболее простым оказалась синхронная реализация в отдельном потоке. Под Win задача была такая — с одной стороны N (около 30-ти плюс-минус) удаленных контроллеров, которые шлют некоторую информацию по UDP протоколу. С другой — M (3-5 обычно) интерфейсных клиентов, которые с этой информацией работают. Поток данных двунаправленный. Информация от контроллера должна быть некоторым образом обработана и на основе определенных признаков отдана одному или нескольким клиентам. Информация от клиента анализируется и передается (на основе анализа) на один из контроллеров.
Все это работает в режиме 24/7. Т.е. постоянно, годами.
Было три потока:
— поток контроллеров с открытым UDP портом в который все контроллеры послылают информацию
— поток клиентов в котором работал TCP сервер и был набор TCP соединений для уже подключившихся клиентов
— поток обработки и маршрутизации
Каждый из потоков создавал свой именованный MailSlot для приема входящей информации. Это оказалось проще чем обмен через память с синхронизацией. Любой поток мог послать данные любому потоку просто записав их в его MailSlot.
На AS-ке задачи другие. Там распараллеливание обработки между задачами (поток не используем т.к. у сопровождения сложности с их мониторингом). Там классическая Batch машина. Одна задача берет данные и подготавливает задания на обработку и несколько обработчиков, которые эти данные параллельно обрабатывают и отдают результат.
Коммуникация была комплексная. Для раздачи заданий использовалась UserQueue — очередь данных. Хороша тем, что в нее кто угодно может писать и кто угодно читать. Она не привязана к конкретному процессу. Головная задача выкладывала туда задания, а обработчики их оттуда разбирали по мере освобождения (выполнил текущее задание — отдал результат — взял из очереди следующее).
Для результатов головная задача держала открытый UnixSocket (DGRAM — он не требует постоянного соединения). Туда обработчики скидывали результаты обработки.
Тоже все работает.
В таких ситуациях (для себя) решил так — обработка в одном потоке, передача — синхрон в отдельном потоке, который уже сам все проблемы разруливает.
Передача файлов с помощью pipes и другие мелочи на Delphi