powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
31 сообщений из 31, показаны все 2 страниц
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600271
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все никак не успокоюсь с "межпроцессорным взаимодействием".

Использовал SendMessage (WM_COPYDATA). WndProc приложения-приемник получает сообщение сразу.
Но подводный камень в том, что приложение-передатчик "висит" до тех пор, пока приложение-приемник не обработает команду и не вернет результат. При этом "обработка команды" в приемнике может занять какое-то время (ну например приемник большой файл конвертирует из одного формата в другой) и "висяк" в передатчике может оказаться критическим, что при большой нагрузке вызовет crash передатчика (ибо его оригинальный код не рассчитан на такой "висяк"). Есть обоснованное подозрение что этот метод вызывает подобные проблемы. PostMessage (WM_COPYDATA) и ему подобные использовать нельзя, т.к. он хоть и не генерирует "висяк", но при этом строка в памяти затирается до того как ее прочтут.

Отсюда вывод: надо использовать другой механизм
Передатчик: "послал-забыл"
Приемник: "прочитал-обработал"

mailslot в этом плане идеален. Даже если в message задан вопрос, на который нужен ответ, то ответ можно послать "обратным мылом", а мне в 99% применений ответ вообще не нужен.

Но вопрос: как мне прочитать сообщение из mailslot сразу как оно там появилось?

В примере:
Reading from a Mailslot
код такой:
Код: plaintext
1.
2.
3.
4.
5.
   while(TRUE)
   {
      ReadSlot();
      Sleep(3000);
   }


То бишь " сообщение прочтется не позднее чем через 3 секунды ".

Категорически не устраивает. Надо сразу .

Простые варианты вижу такие:

В1. Вообще пытаться читать непрерывно
Код: plaintext
1.
2.
3.
4.
   while(TRUE)
   {
      ReadSlot();
   }



В2. Очень маленький интервал
Код: plaintext
1.
2.
3.
4.
5.
   while(TRUE)
   {
      ReadSlot();
      Sleep(100); 
   }



В3. Таймер с очень маленьким интервалом

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SetTimer(hwndWindow,NULL,100,NULL);

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
  switch( message )
  {
    case WM_TIMER:
      ReadSlot();
...



По сути все три метода предполагают непрерывный и бессмысленный долбеж одного и того же кода, что мне и не нравится.
Т.е. насколько вообще чреват высокочастотный долбеж таймерами, когда чего-то ждешь а оно само не стучится (как в случае с оконными сообщениями)?

Вообще я смотрю в описание ф-ции GetMailslotInfo function
GetMailslotInfolpReadTimeout [out, optional]
The amount of time, in milliseconds, a read operation can wait for a message to be written to the mailslot before a time-out occurs. This parameter is filled in when the function returns. This parameter can be NULL.

Во всех примерах и то что я научился использовать, в ReadSlot() применяется конструкция:
Код: plaintext
1.
2.
3.
4.
5.
   fResult = GetMailslotInfo( hSlot, // mailslot handle 
        (LPDWORD) NULL,               // no maximum message size 
        &cbMessage,                   // size of next message 
        &cMessage,                    // number of messages 
        (LPDWORD) NULL);              // no read time-out 


Т.е. ReadSlot возвращает сразу вне зависимости от наличия/отсутствия сообщений.

А м.б. надо сделать так? Не?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
   while(TRUE)
   {
      ...
      fResult = GetMailslotInfo( hSlot, // mailslot handle 
        (LPDWORD) NULL,               // no maximum message size 
        &cbMessage,                   // size of next message 
        &cMessage,                    // number of messages 
        INFINITE;              // ждать пока не появится сообщение 
      ...
      //здесь код обработки сообщения
   }


Исходя из того что в оригинальном main() по любому используется
Код: plaintext
1.
2.
  for (;;)
    PThread::Sleep(5000);


(чтоб приложение не "вышло") то почему бы не воткнуть туда цикл что выше вместо пустого?
main()-поток меня вполне устраивает для обработки message-ей.
Идея правильная?

P.S. Просьба. Не советуйте мне здесь про пайпы (сыт глюко-тестами с ними по горло) или про сокеты (не хочу).
Я задал конкретный вопрос про mailslot.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600283
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77подводный камень в том, что приложение-передатчик "висит" до тех пор, пока
приложение-приемник не обработает команду и не вернет результат.
Если тебе на передатчике этот результат не нужен, просто заставь приёмник быстренько
скопировать данные в свой буфер и верни его сразу, ещё до того как начнёшь обработку.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600285
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

Mailslot (как и пайпы, и сокеты) поддерживают асинхронное чтение
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600287
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Идея правильная?
Правильная идея: выкинуть GetMailslotInfo() к ЧМ и сразу повеситься на ReadFile() пока
сообщение не придёт.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600331
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovДмитрий77подводный камень в том, что приложение-передатчик "висит" до тех пор, пока
приложение-приемник не обработает команду и не вернет результат.
Если тебе на передатчике этот результат не нужен, просто заставь приёмник быстренько
скопировать данные в свой буфер и верни его сразу, ещё до того как начнёшь обработку.

Что касается SendMessage (WM_COPYDATA), то я так и стал делать, когда осознал проблему. Но это не решает проблемы полностью.
Если приемник VB6 (где нет роскоши из многопоточности), то даже простенький результат который "сразу" может вернуться с задержкой, если приемник уже был занят на момент прихода сообщения.
Если приемник C++ с отдельным потоком для возни с сообщениями, то ДА, такой способ прокатит.
Но вот путать код сборной солянкой из SendMessage и MailSlot я точно не хочу.

Dimitry SibiryakovПравильная идея: выкинуть GetMailslotInfo() к ЧМ и сразу повеситься на ReadFile() пока
сообщение не придёт.
Не думаю, что идея правильная. GetMailslotInfo как минимум возвращает lBufferSize -число байтов в сообщении, которое должен читать ReadFile.
А чем плох законный параметр lpReadTimeout = INFINITE в GetMailslotInfo (ну или просто большое число по циклу)? Ну ждет себе и ждет (по документации Microsoft, без долбежа). Как будет сообщение, прочитает его и будет ждать следующего. Типа callBack, только поток висит - ну так этот поток итак ничего не делает.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600336
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

ну сделай отдельным потоком, в этом обсуждении букв больше чем в коде
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600345
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

Код наляпать несложно. Хотя менять IPC метод по всему проекту не наляпав формальной ошибки, это не 5-минутная процедура.
Я вот накатал SendMessage, долго старался, а потом понял подводные камни о кот. упомянул.

Но хотелось бы получить таки четкий ответ на 2 вопроса:

1.Т.е. насколько вообще чреват высокочастотный долбеж таймерами (либо цикл<+Sleep()>), когда чего-то ждешь а оно само не стучится (как в случае с оконными сообщениями)?
Потому что в VB6 например (с одним потоком) таймер- это чуть не единственный способ в такой ситуации. Здесь нужен общий но аргументированный ответ.

2. GetMailslotInfo (INFINITE) -в цикле -это нормальный вариант? В отдельном main() потоке, кот. после инициализации C++ приложения все равно зациклен через Sleep()?
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600364
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

нить начисто потерял. Windows сообщения в программе обрабатываются?

Дмитрий77Исходя из того что в оригинальном main() по любому используется
Код: plaintext
1.
2.
  for (;;)
    PThread::Sleep(5000);


а кто полезную работу делает?
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600381
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропила кто полезную работу делает?

Если интересно, то
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
void Proga::Main()
{
...
  if (!Initialise()) {
    PThread::Sleep(100);  // workaround for race condition
    return;
  }
...
  for (;;)
    PThread::Sleep(5000);
}
-------------------------
PBoolean Proga::Initialise()
{
...
  manager = new MyManager();
  if (!manager->Initialise(args))
    return FALSE;

  return TRUE;
}
--------------------------
PBoolean MyManager::Initialise(const PConfigArgs & args)
{
...
  if (!ModemEndPoint::Create(*this, args))
    return FALSE;
  if (!MyH323EndPoint::Create(*this, args))
    return FALSE;
  if (!MySIPEndPoint::Create(*this, args))
    return FALSE;
  if (!MyCapiEndPoint::Create(*this, args))
    return FALSE;

Дальше цепочку раскручивать (к вопросу отношения не имеет)?

Суть в том, что main() после запуска всего многопоточного хозяйства остается без работы (нулевой цикл чтоб не вышла и вся конструкция не рухнула).
Посему можно думаю ожидание сообщений прям туда и пихать без самопальных CreateThread().
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600385
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилWindows сообщения в программе обрабатываются?
В настоящий момент ДА.
Через при-аттаченное мной к консоли окно.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
  char t[500];
  GetConsoleTitleA( t, 1000 );     // retrieve the text of the title bar of the console window
  HWND hwndConsole = FindWindowA( NULL, t );
  HINSTANCE hInstance = (HINSTANCE)(LONG_PTR)GetWindowLong(hwndConsole, GWL_HINSTANCE);
  static const char* class_name = "MYPROGA_WINDOW_CLASS";
  WNDCLASSEX wx = {};
  wx.cbSize = sizeof(WNDCLASSEX);
  wx.lpfnWndProc = WndProc;        // function which will handle messages
  wx.hInstance = hInstance;
  wx.lpszClassName = class_name;
  if ( RegisterClassEx(&wx) ) {
    HWND hwndWindow = CreateWindowEx( 0, class_name, "MyProga_Message_Receiver", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );


Но я хочу это окно вообще убрать и принимать Message-ы на mailslot.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600386
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

ну тогда спокойно крути в цикле ReadFile с большим таймаутом
GetMailslotInfo - не нужен в данном случае, максимальный размер сообщения при создании мейлслота известен.

В вот когда потребуется ожидать одно событие из нескольких -тогда другой разговор будет
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600387
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Но я хочу это окно вообще убрать и принимать Message-ы на mailslot.
убирай, в чём проблема( кстати, окно не обязано быть видимым)
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600389
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилмаксимальный размер сообщения при создании мейлслота известен
Ну, я макс. размер никогда не ограничиваю:
Код: vbnet
1.
hMailSlotHandle = CreateMailslot(lpszSlotName, 0, 0, m_tSA)


Хотя там кажется есть документальное ограничение.

Изопропилну тогда спокойно крути в цикле ReadFile с большим таймаутом
GetMailslotInfo - не нужен в данном случае,
А почему вы все так дружно против GetMailslotInfo с большим/бесконечным таймаутом?
У меня ощущение что суть там одна.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600391
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А почему вы все так дружно против GetMailslotInfo
потому что он просто не нужен
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600392
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилДмитрий77Но я хочу это окно вообще убрать и принимать Message-ы на mailslot.
убирай, в чём проблема( кстати, окно не обязано быть видимым)
Конечно уберу.
Тем более в связи с этим окном у меня main() счас делает другой цикл:
Код: plaintext
1.
2.
3.
4.
5.
6.
    MSG msg;
    while( GetMessage( &msg, hwndWindow, 0, 0 ) )
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }



А кто сказал, что оно видимо.
Оно же у меня HWND_MESSAGE (специально для этих целей).
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600438
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторGetMailslotInfo с большим/бесконечным таймаутом?
Похоже это не то и любая попытка задать там что-либо отличное от
(LPDWORD) NULL); // no read time-out
приводит к крашу.

Dimitry SibiryakovПравильная идея: выкинуть GetMailslotInfo() к ЧМ и сразу повеситься на ReadFile() пока
сообщение не придёт.
Ты мне вот это предлагаешь?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
  MakeMailSlot(Slot);

  char buffer[65536];
  DWORD NumberOfBytesRead;

 // Read data from the mailslot forever!
  while(ReadFile(hMailSlotHandle, buffer, 65536, &NumberOfBytesRead, NULL) != 0)
  {
    PString str_buf = PString((LPCTSTR)buffer);
    cout << str_buf << " " << NumberOfBytesRead << "\n";
  }



Ну, в принципе это работает (по предварительным тестам).

Но у меня вопросы:
1) Это ж отвратительный долбеж. Хуже чем таймер или Sleep(). Не?
2) Где гарантия что я не прочту 2 сообщения разом? Или что не прочту "кусок", а второй "кусок" будет прочитан в следующий раз?
3) Какой правильно брать размер buffer[]? При создании mailslot я не задаю максимальный размер:
Код: plaintext
1.
2.
3.
4.
  hMailSlotHandle = CreateMailslot(lpszSlotName, 
                     0,                             // no maximum message size 
                     MAILSLOT_WAIT_FOREVER,         // no time-out for operations 
                     (LPSECURITY_ATTRIBUTES) NULL); // default security


По логике 65536 явный перебор конечно. Я же знаю примерную структуру своих сообщений. Но с другой стороны, сколько раз накалывался: пишешь 256, а что-нибудь куда-нибудь добавил и получаем обрубки строк.
С другой стороны у меня есть NumberOfBytesRead и если оно равно запрашиваемому, то запросить след. порцию байтов как остаток строки. Но с этим возиться неохота.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600445
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Если приемник VB6 (где нет роскоши из многопоточности)....
Напиши DLL на Си, в нее вынеси поток приема сообщений и постановку в очередь, а из VB бери из очереди и обрабатывай.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600446
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть уже готовые опенсорцные DLL для обмена сообщениями. Вот пример использования. Под твою задачу подходит идеально.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600454
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

Давай VB пока в покое оставим и SendMessage задвинем. На стороне VB я думаю удовлетворюсь таймером чтения mailslot скажем в 300мс и меня это вполне устроит.

А вот на стороне C++ я хочу грамотно читать mailslot как только так сразу.

Ну в принципе кажется уловил.
Если написать код в виде:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  MakeMailSlot(Slot);

  char buffer[65536];
  DWORD NumberOfBytesRead;
  for (;;)
  {
    if (ReadFile(hMailSlotHandle, buffer, 65536, &NumberOfBytesRead, NULL)!=0) {
      buffer[NumberOfBytesRead]='\0'; //отсекаем мусор
      PString str_message =  PString((LPCTSTR)buffer);
      cout << str_message << "\n";
      //обработка str_message
    }
    else
      cout << "timeout\n";
  }



и при этом задать
Код: plaintext
1.
2.
3.
4.
5.
6.
BOOL WINAPI MakeMailSlot(LPTSTR lpszSlotName) 
{ 
  hMailSlotHandle = CreateMailslot(lpszSlotName, 
                     0,                             // no maximum message size 
                     10000,         // wait 10sec
                     (LPSECURITY_ATTRIBUTES) NULL); // default security


то слово "timeout" будет писаться раз в 10 секунд

а если
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 BOOL WINAPI MakeMailSlot(LPTSTR lpszSlotName) 
{ 
  hMailSlotHandle = CreateMailslot(lpszSlotName, 
                     0,                             // no maximum message size 
                     MAILSLOT_WAIT_FOREVER,         // no time-out for operations
                     (LPSECURITY_ATTRIBUTES) NULL); // default security
 


то слово "timeout" вообще никогда писаться не будет

Т.е. никакой "долбежки" там нет, все чудненько, с MAILSLOT_WAIT_FOREVER -идеально.

Ну тогда 2 вопроса осталось:
автор2) Где гарантия что я не прочту 2 сообщения разом? Или что не прочту "кусок", а второй "кусок" будет прочитан в следующий раз?
3) Какой правильно брать размер buffer[]? При создании mailslot я не задаю максимальный размер:
Де-факто гарантия вроде как есть, а размер можно думаю задать побольше но не слишком, напр. char buffer[1000];
То что мусор надо ручками отсекать '\0'-символом это я уже понял после пары тестов.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600458
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77То что мусор надо ручками отсекать '\0'-символом это я уже понял после пары тестов.
Тут похоже у тебя ошибка проектирования. Подозреваю что ты вынужден насильно отсекать т.к. ты этот 0 не передаешь, отсюда проблемы с разделением сообщений.
Если тебе надо передать строку "12345" то отправлять надо 6 символов, т.к. реально это массив {'1','2','3',4','5',0}

Не помещает немного формат сообщения усложнить, дополнить контрольной инфой для проверки что сообщения полное. Если у тебя строки передаются, то я бы так сделал: строка из двух частей "NN\tTTTT" где NN размер, TTTT текст сообщения. Например "5\tABCDE", далее отправляешь 8 байт при получении проверяешь что последний 0 и формат соблюдается 5 == strlen("ABCDE"), если что-то не совпало - отправляешь обратно "syntax error", формат соблюден - обрабатываешь.

По поводу MAILSLOT_WAIT_FOREVER - недостаток один: выйти из цикла сможешь только по команде извне. С маилслотами не работал, но думаю не помешает какой-то контроль что слот не умер, иначе зациклится постоянно выпадывая в else
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600471
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TДмитрий77То что мусор надо ручками отсекать '\0'-символом это я уже понял после пары тестов.
Тут похоже у тебя ошибка проектирования. Подозреваю что ты вынужден насильно отсекать т.к. ты этот 0 не передаешь, отсюда проблемы с разделением сообщений.
Правильно подозреваешь.
Я тестировал VB-шной ф-цией:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Public Function SendMessageToMailSlot(ByVal sMessage As String, ByVal sMailSlot As String) As Boolean
  'ПЕРЕДАТЧИК(клиент)ф-ция отправляет сообщение sMessage серверу с именем sMailSlot
  'если сервер не запущен, то сообщение не отправляется
  Dim hFile As Long
  Dim m_tSA As SECURITY_ATTRIBUTES
  
  hFile = CreateFile(sMailSlot, _
                     GENERIC_WRITE, _
                     FILE_SHARE_READ, _
                     m_tSA, _
                     OPEN_EXISTING, _
                     FILE_ATTRIBUTE_NORMAL)
  If hFile = INVALID_HANDLE_VALUE Then Exit Function
  
  SendMessageToMailSlot = WriteFile(hFile, sMessage, Len(sMessage))
  CloseHandle hFile
End Function



И ф-ция эта писалась под VB->VB, а не под VB->C++

Но там другой принцип считывания (я использую GetMailslotInfo).

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
Public Function MailSlotReadFirst(ByRef m_Message As String, ByRef m_MsgCount As Long) As Boolean
  'ПРИЕМНИК(сервер) ф-ция читает первое сообщение если есть
  'возвращает True, если есть хотя бы одно и оно было прочитано
  'm_Message (Out)-текст сообщения, если прочли
  'm_MsgCount -к-во сообщений оставшихся после чтения (без учета прочитанного)
  Dim lBufferSize As Long
  m_Message = ""
  m_MsgCount = 0
  GetMailslotInfo hMailSlotHandle, 0, lBufferSize, m_MsgCount, 0
  If m_MsgCount > 0 Then
    Dim sBuffer As String, lBytesRead As Long
    ' Create a buffer
    sBuffer = String(lBufferSize, 0)
    
    ' Read data: optional параметры ф-ции не используем
    If ReadFile(hMailSlotHandle, sBuffer, lBufferSize) Then
      m_Message = sBuffer
      m_MsgCount = m_MsgCount - 1
      MailSlotReadFirst = True
    End If
  End If
End Function



И мне там этот '\0' извини нафиг не нужен, если я его буду дописывать у меня на VB-приемнике ничего кроме лишних проблем не добавится.

А в C++ у меня массив чаров, да я еще и один и тот же(с избытком длины) использую. Естественно без '\0' он мне его не обрубает.
Ну, согласен, надо тогда в сторону C++ mailslot-а чуть модифицированной ф-цией посылать:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Public Function SendMessageToMailSlotCPP(ByVal sMessage As String, ByVal sMailSlot As String) As Boolean
  'ПЕРЕДАТЧИК(клиент)ф-ция отправляет сообщение sMessage серверу с именем sMailSlot
  'если сервер не запущен, то сообщение не отправляется
  Dim hFile As Long
  Dim m_tSA As SECURITY_ATTRIBUTES
  
  hFile = CreateFile(sMailSlot, _
                     GENERIC_WRITE, _
                     FILE_SHARE_READ, _
                     m_tSA, _
                     OPEN_EXISTING, _
                     FILE_ATTRIBUTE_NORMAL)
  If hFile = INVALID_HANDLE_VALUE Then Exit Function
  
  SendMessageToMailSlotCPP = WriteFile(hFile, sMessage, Len(sMessage) + 1)
  CloseHandle hFile
End Function
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600476
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А в C++ у меня массив чаров, да я еще и один и тот же(с избытком длины) использую. Естественно без '\0' он мне его не обрубает.
Ну, согласен, надо тогда в сторону C++ mailslot-а чуть модифицированной ф-цией посылать ...

не уверен что VB хранит последний 0, лучше так чтобы наверняка:
Код: plaintext
1.
  SendMessageToMailSlotCPP = WriteFile(hFile, sMessage + chr(0), Len(sMessage) + 1)
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600485
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tт.к. ты этот 0 не передаешь, отсюда проблемы с разделением сообщений.
Не, проблем с разделением из-за этого точно не возникает. Я вообще пока проблем с разделением не вижу. Я просто спросил: а вдруг?
Dima TНе помещает немного формат сообщения усложнить, дополнить контрольной инфой для проверки что сообщения полное. Если у тебя строки передаются, то я бы так сделал: строка из двух частей "NN\tTTTT" где NN размер, TTTT текст сообщения. Например "5\tABCDE", далее отправляешь 8 байт при получении проверяешь что последний 0 и формат соблюдается 5 == strlen("ABCDE"), если что-то не совпало - отправляешь обратно "syntax error", формат соблюден - обрабатываешь..
Ну, не думаю что эти усложнения нужны

Dima TПо поводу MAILSLOT_WAIT_FOREVER - недостаток один: выйти из цикла сможешь только по команде извне.
Имя этой волшебной команды "taskkill.exe" -ну или API в том же духе.

Dima TС маилслотами не работал, но думаю не помешает какой-то контроль что слот не умер, иначе зациклится постоянно выпадывая в else
Ну, судя по опыта внедрения слот вещь неубиваемая, пока жив процесс.
Проблема может возникнуть при создании слота, если уже запущен экземпляр приложения (!!! в том числе и под другим аккаунтом). Т.е. на одном компе не может быть двух слотов с одним именем.
Ну, с SendMessage проблема такая же, отправитель найдет только одно окно (если их несколько) туда и будет посылать. Но, правда не совсем. Будет найдено окно под своим аккаунтом.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600490
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tне уверен что VB хранит последний 0, лучше так чтобы наверняка:
Код: plaintext
1.
  SendMessageToMailSlotCPP = WriteFile(hFile, sMessage + chr(0), Len(sMessage) + 1)


В данном случае это добавление бессмысленно. При конвертации vb String в C++ ноль дописывается автоматически.
Просто без +1 он не пишется в сообщение.

Вот за этим то я его и убил в VB->VB чтоб исключить "не уверен, лучше так чтобы наверняка".
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600491
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Dima Tт.к. ты этот 0 не передаешь, отсюда проблемы с разделением сообщений.
Не, проблем с разделением из-за этого точно не возникает. Я вообще пока проблем с разделением не вижу. Я просто спросил: а вдруг?
Есть подозрение что доставляются сообщения по одному, т.к. это все-таки подсистема ориентированная на сообщения, а не на потоковую передачу. Поизучай MSDN, если найдешь что гарантируется доставка всегда по одному и целиком, то вообще можешь не заморачиваться с нулями, а отсекать нулем как изначально сделал.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600498
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно опытным путем проверить:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
  MakeMailSlot(Slot);

  char buffer[65536];
  DWORD NumberOfBytesRead;
  for (;;)
  {
    Sleep(1000);
    GetMailslotInfo(..., MsgCount ...); // получение количества в очереди
    cout << MsgCount << " msg\n";
    if (ReadFile(hMailSlotHandle, buffer, 65536, &NumberOfBytesRead, NULL)!=0) {
      buffer[NumberOfBytesRead]='\0'; //отсекаем мусор
      PString str_message =  PString((LPCTSTR)buffer);
      cout << str_message << "\n";
      //обработка str_message
    }
    else
      cout << "timeout\n";
  }


Вставь Sleep(), GetMailslotInfo() только чтобы видеть сколько в очереди на текущий момент.
Отправь подряд 10 сообщений и посмотри как примутся. Если GetMailslotInfo() покажет что больше одного в очереди, а примет по одному, то считай что ReadFile() читает по одному, а не пачкой.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600536
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Проблема может возникнуть при создании слота, если уже запущен экземпляр приложения (!!! в том числе и под другим аккаунтом). Т.е. на одном компе не может быть двух слотов с одним именем.
Как вариант использовать ProcessID и добавлять его в имя слота. Двух работающих процессов с одинаковым ProcessID быть не может, даже под разными пользователями.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38600579
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Имя этой волшебной команды "taskkill.exe" -ну или API в том же духе.
это только от бессилия. приложение по-возможности закрывать аккуранто следует (дабы всё записалось,
ресурсы освободились - чудес нет, утекать может всё что угодно)
Дмитрий77Проблема может возникнуть при создании слота, если уже запущен экземпляр приложения
всё зависит от того, что ты хочешь сделать.
передававть свои команды всем?
или запрещать запуск второго экземпляра?
или устанавливать связь с запускаемым приложением(пользователь не запускает приложение самостоятельно)?
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38601083
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил, Dima T

Спасибо за участие. Но вы вот сейчас начинаете копать архитектуру проекта и давать общие советы.
Как приложение закрывать, как длину сообщения проверять, как еще 10 dll-к подключать.
Будто я тут школьник и всего этого не знаю и не понимаю.
Не запускается у меня по логике 2 экземпляра.
И for(;;) Sleep(5000) на конце main() не я придумал и я даже знаю чем это напр. реально чревато:
в одном из 100 случаев запущенная заново прога не сумеет сразу зарегистрироваться на SIP сервере (если сервер не получил UnRegister и контролирует число регистраций). Но извите, если не бухать сразу, то все эти енд-пойнты будут грамотно закрываться секунд 5, и в 99% случаев мне от этого не жарко не холодно ну и т.д.
Просто если пытаться "контролировать" все и вся и сильно умничать, то можно такое навернуть, что оно потом будет ошибаться больше и чаще чем более менее простой оригинал, и уже фиг вообще чего поймешь в этом в случае ошибок.
Такие проекты лучше сразу писать "без ошибок", чем пытаться контролировать надуманные ошибки вероятность которых весьма сомнительна. Скорее погоришь на своем "развернутом контролировании".

Но вот ответ на вопрос:
2) Где гарантия что я не прочту 2 сообщения разом? Или что не прочту "кусок", а второй "кусок" будет прочитан в следующий раз?
-его да, лучше знать.
Тесты типа того что предложил Dima T - ну вроде как показывают что "не пересекаются".
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38601275
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Изопропил, Dima T

Спасибо за участие. Но вы вот сейчас начинаете копать архитектуру проекта и давать общие советы.
Не хочешь - не обращай внимания, по существу уже все сказано.

Дмитрий77Но вот ответ на вопрос:
2) Где гарантия что я не прочту 2 сообщения разом? Или что не прочту "кусок", а второй "кусок" будет прочитан в следующий раз?
-его да, лучше знать.
Тесты типа того что предложил Dima T - ну вроде как показывают что "не пересекаются".
Тут гарантированно тебе может ответить только разработчик, т.е. MS. А они в MSDN не пишут явно что "не пересекаются". Я почитал что про маилслоты там пишут (сам подумываю их попользовать) нет такого. Может просто забыли написать, может я невнимательно читал.
Максимум что можешь: потестить дополнительно на разных виндовсах и решить для себя что "не пересекаются", тем более (как я понял) зашита от потерь у тебя есть.
...
Рейтинг: 0 / 0
Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
    #38601316
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Будто я тут школьник и всего этого не знаю и не понимаю.
временами очень похоже
...
Рейтинг: 0 / 0
31 сообщений из 31, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как сделать так чтоб сообщения из mailslot читались "сразу как оно там появится"?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]