Здравствуйте!
Имеется следующая задачка. Запускается до дюжины консольных приложений. Они должны обмениваться между собой данными, но не абы как, а по следующим правилам:
отправляющий процесс вызывает некую процедуру Send, передает ей указатель на массив данных, размер массива и ID процесса-получателя;
принимающий процесс вызывает процедуру Recv, передает ей указатель на буфер, в котором будут сохраняться данные, их размер и ID процесса-отправителя
Сложность состоит в том, что процедура Send не должна дожидаться, пока данные отправятся и будут приняты, а возвращать управление сразу. Так же и Recv только добавляет запрос на получение данных, но не дожидается, пока буфер приема будет заполнен. Кроме того, вовсе не обязательно, что сначала будет вызван Send, а потом Recv. Порядок вызова этих процедур может быть совершенно произвольным.
Буду очень благодарен, если кто-нибудь подскажет, при помощи каких механизмов Windows 95/98 можно организовать такое взаимодействие.
Тот, кто желает, но не делает, распространяет чуму.
V> Буду очень благодарен, если кто-нибудь подскажет, при помощи каких механизмов Windows 95/98 можно организовать такое взаимодействие.
При помощи таких же как и в DOS ;) — ручками.
Можно по старинке сохранять посылаемые сообщения в файлы (для каждого процесса в отдельный), и делать это используя блокировку. Но более современно, наверное, будет использовать мапинг и объекты сихронизации.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте volk, вы писали:
V> Буду очень благодарен, если кто-нибудь подскажет, при помощи каких механизмов Windows 95/98 можно организовать такое взаимодействие.
Если я правильно понял задачу.
Алгоритм реализации взаимодействия полностью ложится на тебя.
А средства для реализации межпроцессного обмена данными есть разные.
— сообщения (WM_COPYDATA в частности)
— разделяемая память (см. CreateFileMapping с передачей INVALID_HANDLE_VALUE в качестве hFile)
— поименованные каналы (NamedPipes)
— DCOM
Здравствуйте Willi, вы писали:
W>- сообщения (WM_COPYDATA в частности) W>- разделяемая память (см. CreateFileMapping с передачей INVALID_HANDLE_VALUE в качестве hFile) W>- поименованные каналы (NamedPipes) W>- DCOM
Только замечание: поименованные каналы (они же трубы, они же пайпы, они же пипки :-) ) в Win95/98 не поддерживаются, поддерживаются безымянные (анонимные).
Большое спасибо за внимание к вопросу. Я последовал советам и попытался применить все перечисленное. Но увы ...
1) Файлы, проецируемые в память использовать придется. Но представьте такую ситуацию: процесс выполняет Recv, а соответсвующий Send в другом процессе не выполнен. Тогда, по-видимому, процесс-приемник создает проецируемый файл (можно это так назвать?) с заранее известным именем. Потом процесс-отправитель выполняет, наконец, Send, открывает тот же проецируемый файл и что-то в него пишет. А как теперь перекинуть данные из общего файла в буфер процесса-приемника? Приемник этим заниматься не может, поскольку занят выполнением своей задачи, а других функций взаимодействия, кроме Recv, в нем нет (по условию). Должен найтись кто-то третий, имеющий доступ в адресное пространство приемника. Этот третий и должен переписать данные в буфер приемника.
Но кто этот "третий" и как такое реализовать?
2) Объекты синхронизации заставляют процесс ждать когда освободится для доступа память, либо когда произойдет какое-то событие. Ждать нельзя, кроме того, может получиться так, что ждать придется вечно.
3) Сообщений дожидаться не надо, но их нужно принимать и обрабатывать. А для этого в программе (программах) опять же должны иметься какие-то еще процедуры кроме этих самых Send и Recv. Но их там быть не может по условию.
По скудости ума своего я так и не понял, что такое mailslot. Может, это то, что мне нужно?
Да, забыл добавить. Все это должно использоваться только для отладки, поэтому скорость выполнения и объем "пожираемых" ресурсов несущественнен.
Тот, кто желает, но не делает, распространяет чуму.
V>1) Файлы, проецируемые в память использовать придется. Но представьте такую ситуацию: процесс выполняет Recv, а соответсвующий Send в другом процессе не выполнен. Тогда, по-видимому, процесс-приемник создает проецируемый файл (можно это так назвать?) с заранее известным именем. Потом процесс-отправитель выполняет, наконец, Send, открывает тот же проецируемый файл и что-то в него пишет. А как теперь перекинуть данные из общего файла в буфер процесса-приемника? Приемник этим заниматься не может, поскольку занят выполнением своей задачи, а других функций взаимодействия, кроме Recv, в нем нет (по условию). Должен найтись кто-то третий, имеющий доступ в адресное пространство приемника. Этот третий и должен переписать данные в буфер приемника. V> Но кто этот "третий" и как такое реализовать?
Этот третий — Windows. Не надо Вам никаких буферов, проецируемый файл — это уже есть память (см. CreateFileMapping). Про когерентность (coherence) посмотрите. Думайте о проекции как об общем блоке памяти, только в разных процессах он может быть в разных адресах, но содержимое будет одинаковым. Не забывайте, что, как и любая общая память, заполняется он асинхронно от чтения, поэтому либо нужна синхронизация, либо данные должны быть самосинхронизирующиеся — то есть из содержимого либо должно быть понятно, что оно дописалось, либо это должно быть неважно (например, просмтаривается просто текущее состояние массива).
Здравствуйте volk, вы писали:
V> Имеется следующая задачка. Запускается до дюжины консольных приложений. Они должны обмениваться между собой данными, но не абы как, а по следующим правилам: V> отправляющий процесс вызывает некую процедуру Send, передает ей указатель на массив данных, размер массива и ID процесса-получателя; V> принимающий процесс вызывает процедуру Recv, передает ей указатель на буфер, в котором будут сохраняться данные, их размер и ID процесса-отправителя V> Сложность состоит в том, что процедура Send не должна дожидаться, пока данные отправятся и будут приняты, а возвращать управление сразу. Так же и Recv только добавляет запрос на получение данных, но не дожидается, пока буфер приема будет заполнен. Кроме того, вовсе не обязательно, что сначала будет вызван Send, а потом Recv. Порядок вызова этих процедур может быть совершенно произвольным.
V> Буду очень благодарен, если кто-нибудь подскажет, при помощи каких механизмов Windows 95/98 можно организовать такое взаимодействие.
Я так понимаю, сам механизм обмена данными основан на принципе "поточноти" (streaming).
Самый простой на мой взгляд способ -- это механизм сокетов. Работает просто и со вкусом, а если пользовать Windows Sockets 2, то ещё и асинхронно.
Т.е. идея состоит в том, чтобы написать ма-а-асенький сервак (a-la echo service). Send & Recv уже есть...
Можно спокойно использовать WM_COPYDATA вкупе с DDE, только юзать не SendMessage, а PostMessage
А вот при использоваении shared-memory или FileMapping, можно поиметь кучу геморроя...
Да, кстати, всегда остается возможность попользовать ReadProcessMemory() && WriteProcessMemory(), но у меня складывается впечатление, то применение данных фишек будет просто нерименимо.
Здравствуйте, TSS, Вы писали:
TSS>Самый простой на мой взгляд способ -- это механизм сокетов. Работает просто и со вкусом, а если пользовать TSS>Windows Sockets 2, то ещё и асинхронно.
Да и в первых сокетах есть не блокируемый режим. TSS>Т.е. идея состоит в том, чтобы написать ма-а-асенький сервак (a-la echo service). Send & Recv уже есть...
А если посылать по UDP то и соединения не нужно устанавливать. И сервак не нужно писать, просто каждый процесс будет по своему UDP порту делать Recv своих сообщений и на порту нужного процесса посыдать Send.
при этом никаких бокировок не будет, как послал, так и освободился. А роль буфера будет операционка выполять со своим стеком TCP/IP.