Blog. Just Blog

Передача данных между процессами с помощью Mailslot

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Mailslot - один из самых простых способов обмена данными между процессами, который работает еще со времен Windows 95. Каналы Mailslot позволяют передавать данные от одного или нескольких клиентов к одному или нескольким серверам, в том числе в широковещательном режиме. На локальном компьютере может быть один серверный процесс, но в сети или в домене может одновременно работать несколько серверов. Количество клиентских приложений не ограничено. Принцип работы Mailslot схож с работой электронной почты.

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

Для создания канала используется функция CreateMailslot, которая в качестве одного из параметров принимает имя канала. Имя канала для серверного приложения должно иметь вид \\.\mailslot\имя_канала, при этом имя должно быть уникальным для приложения, но одинаковым в пределах клиента и сервера. Создавать канал должна серверная часть приложения. Она же определяет максимальный размер передаваемых сообщений и время ожидания. В случае необходимости этот параметр можно менять при помощи функции SetMailslotInfo.

Получив хэндл канала, сервер будет читать из него присланные сообщения. Обработчик выполняется в цикле по таймеру или же в отдельном потоке с задержкой между итерациями. Каждый шаг цикла начинается с получения состояния канала, это делается при помощи функции GetMailslotInfo, она возвращает количество сообщений в очереди на момент запроса и размер сообщения, которое будет получено первым. Если сообщений в очереди нет, то после выполнения функции параметр lpMessageCount будет равен нулю, а параметр lpNextSize примет значение MAILSLOT_NO_MESSAGE. Полученные сообщения читаются из канала функцией ReadFile, будто из обычного текстового файла.

Таким образом, простейшее серверное приложение для работы с Mailslot будет иметь следующий вид:
  1. proc DialogProc hwnddlg,msg,wparam,lparam
  2.         push    ebx esi edi
  3.         cmp     [msg],WM_INITDIALOG
  4.         je      .wminitdialog
  5.         cmp     [msg],WM_COMMAND
  6.         je      .wmcommand
  7.         cmp     [msg],WM_CLOSE
  8.         je      .wmdone
  9.         cmp     [msg],WM_TIMER
  10.         je      .wmtimer
  11.         xor     eax,eax
  12.         jmp     .finish
  13. .wminitdialog:
  14.         ; Создать канал получения данных
  15.         invoke  CreateMailslot,mailslot,0,\
  16.                 MAILSLOT_WAIT_FOREVER, NULL
  17.         cmp     eax,INVALID_HANDLE_VALUE
  18.         je      .wmclose
  19.         mov     [hMailSlot],eax
  20.  
  21.         ; Установить таймер для обработки канала
  22.         invoke  SetTimer,[hwnddlg],1,100,NULL
  23.  
  24.         jmp     .processed
  25. .wmcommand:
  26.         cmp     [wparam],BN_CLICKED shl 16 + IDCANCEL
  27.         je      .wmdone
  28.         jmp     .processed
  29.  
  30. .wmtimer:
  31.         ; Получить состояние канала
  32.         invoke  GetMailslotInfo,[hMailSlot],NULL,dSize,dNum,NULL
  33.         cmp     [dNum],0
  34.         je      .processed
  35.  
  36.         ; Получить данные из канала
  37.         invoke  ReadFile,[hMailSlot],buff,[dSize],tmp,NULL
  38.         ; buff -> текст сообщения
  39.  
  40.         jmp     .processed
  41.  
  42. .wmdone:
  43.         ; Удалить таймер и закрыть канал
  44.         invoke  KillTimer,[hwnddlg],1
  45.         invoke  CloseHandle,[hMailSlot]
  46. .wmclose:
  47.         invoke  EndDialog,[hwnddlg],0
  48. .processed:
  49.         mov     eax,1
  50. .finish:
  51.         pop     edi esi ebx
  52.         ret
  53. endp
Переходим к клиентскому приложению. Оно может работать только с уже существующим каналом, который создала серверная часть приложения. Канал открывается фнукцией CreateFile. В качестве имени файла используется имя канала, аналогичное имени серверного канала, но для локального процесса оно должно иметь вид \\.\mailslot\имя_канала, для конкретной рабочей станции \\название_станции\mailslot\имя_канала, для широковещательных рассылок в домене имя будет \\имя_домена\mailslot\имя_канала или \\*\mailslot\имя_канала для передачи сообщений одновременно всем доступным рабочим станциям. Режим доступа к файлу должен быть GENERIC_WRITE, так как клиентское приложение может только отправлять данные в канал, а режим совместной работы FILE_SHARE_READ, чтобы с одним каналом могли одновременно работать несколко клиентов. Также обязательно надо указывать флаг OPEN_EXISTING, чтобы клиент работал только с существующим каналом. Отправка данных в канал выполняется функцией WriteFile. При отправке широковещательных рассылок размер сообщения принудительно ограничивается 424 байтами.

Собираем все вместе и получаем заготовку клиентского приложения.
  1. proc DialogProc hwnddlg,msg,wparam,lparam
  2.         push    ebx esi edi
  3.         cmp     [msg],WM_INITDIALOG
  4.         je      .wminitdialog
  5.         cmp     [msg],WM_COMMAND
  6.         je      .wmcommand
  7.         cmp     [msg],WM_CLOSE
  8.         je      .wmdone
  9.         xor     eax,eax
  10.         jmp     .finish
  11. .wminitdialog:
  12.         ; Открыть существующий канал
  13.         invoke  CreateFile,mailslot,GENERIC_WRITE,\
  14.                 FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL
  15.         cmp     eax,INVALID_HANDLE_VALUE
  16.         je      .wmclose
  17.         mov     [hMailslot],eax
  18.  
  19.         jmp     .processed
  20. .wmcommand:
  21.         cmp     [wparam],BN_CLICKED shl 16 + IDCANCEL
  22.         je      .wmdone
  23.         cmp     [wparam],BN_CLICKED shl 16 + ID_SEND
  24.         je      .wmsend
  25.         jmp     .processed
  26.  
  27. .wmsend:
  28.         ; Отправить сообщение в канал
  29.         invoke  WriteFile,[hMailslot],szMessage,[dSize],tmp,NULL
  30.         jmp     .processed
  31.  
  32. .wmdone:
  33.         ; Закрыть канал
  34.         invoke  CloseHandle,[hMailslot]
  35. .wmclose:
  36.         invoke  EndDialog,[hwnddlg],0
  37. .processed:
  38.         mov     eax,1
  39. .finish:
  40.         pop     edi esi ebx
  41.         ret
  42. endp
В приложении примеры программ с исходными текстами, которые демонстрируют работу клиентского и серверного приложения с каналами Mailslot.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Mailslot.Demo.zip (4,789 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 407 | Комментариев: 0

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0049 сек.) / Память: 4.5 Mb
Наверх