IPC на терминальном сервере с C/C++ и nw.js/node.js/node-native-module (C++)?

У меня есть Win32-DLL (C++), которая загружается как плагин в другое приложение. DLL запускает экземпляр nw.js (ShellExecuteEx и SEE_MASK_NOCLOSEPROCESS) и завершает его при выгрузке DLL (посредством hInstance ShellExecuteEx). Мне нужен способ отправить строку (обычный ansi) в nw-процесс и получить ответ (также строку). По старинке был простой http-запрос с ответом в теле. Но среда изменяется во время разработки, "пакет" app-dll-nw запускается несколько раз одним и тем же пользователем, а несколько пользователей запускаются на одном компьютере (терминальном сервере). Таким образом, перечисление портов "невозможно" (да, случайные порты или синглтон nw, но нет).

Я нашел разные способы:

  • сокет - проблема с перечислением портов
  • wm_copydata/wm_... - нужен собственный плагин nw со скрытым окном (без нативного способа nw); нет системы запрос-ответ
  • RPC - проблема с перечислением портов
  • DDE - нет нативного способа javascript (найден модуль, который использует.net); В старые времена Delphi DDE была не такой простой задачей, и она несколько раз терпела неудачу без какой-либо логики.
  • общая память - нет опыта; ожидания: асинхронный, триггер?
  • общий файл - нет опыта; ожидания: асинхронный, триггер (наблюдатель за изменением файла), но проблемы с синхронизацией, возможен собственный способ js
  • именованная труба - нет опыта; ожидания: win32-api и т.п. как система чата (in-pipe [отправить трансляцию] и out-pipe [принять трансляцию], или оба в одном)? Если да, я могу использовать одно имя для всех экземпляров, использовать уникальные идентификаторы и ждать правильного ответа.

Что такое хороший и простой способ общения, такой как http-way, но без сетевого взаимодействия?

Обновление 1: модуль узла "net" может создать сервер для именованного канала. Первый тест, послав строку из dll в nw, прошел успешно.

var server = net.createServer(function(stream) {
      stream.on('data', function(c) {
        console.log('data:', c.toString());
      });
      stream.on('end', function() {
        //server.close();
      });
    });
    server.listen('\\\\.\\pipe\\MyAppDynamicGUID');

Обновление 2 - Мое решение

С именованным каналом и упрощенной версией https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx я нашел работающий метод.

Сервер в nw.js:

var server = net.createServer(function(req) {
    req.on('data', function(c) {
        console.log(c.toString());
        req.write('123|Hello World', 'ascii');
    });
});
server.listen('\\\\.\\pipe\\MyAppDynamicGUID');

Клиент на C++ (без постоянного соединения, странная обработка строк, упрощенная обработка ошибок):

static std::string PipenameA = "\\\\.\\pipe\\MyAppDynamicGUID";
#define BUFSIZE 512
std::string SendPipeRequestA(std::string sRequest) {
    DWORD dwToWrite, dwWritten, dwRead;
    BOOL bSuccess;
    char chBuf[BUFSIZE];
    std::vector<char> buffer;
    HANDLE hPipe = CreateFileA(PipenameA.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hPipe == INVALID_HANDLE_VALUE)
        return "-1|Pipe-Error 1 (connect)";
    dwToWrite = (lstrlenA(sRequest.c_str())+1)*sizeof(char);
    bSuccess = WriteFile(hPipe, sRequest.c_str(), dwToWrite, &dwWritten, NULL);
    if (!bSuccess)
        return "-1|Pipe-Error 2 (write)";
    do { 
        bSuccess = ReadFile(hPipe, chBuf, BUFSIZE*sizeof(char), &dwRead, NULL);
        if (!bSuccess && GetLastError() != ERROR_MORE_DATA)
            break;
        buffer.insert(buffer.end(), chBuf, chBuf + dwRead);
    } while (!bSuccess);
    std::string sResponse(&buffer[0]);
    CloseHandle(hPipe);
    return sResponse.c_str();
}

// Джонни

2 ответа

Ответы, которые вы получите, будут основаны на мнении, знайте об этом.

Вы можете ввести данные в модуль JS в качестве аргумента командной строки, напримерstart nw.js MyDataи получить его в JS с process.argv,

Теперь отправка данных обратно в исполняемые файлы / библиотеки C++ немного сложна. если вы выполняете shell-процесс, вы можете иметь дескриптор к нему. Вы можете распечатать данные в стандартный вывод из части JS и прочитать их в собственном приложении, получив дескриптор STDOUT из дескриптора процесса.

Зарегистрировать ваше приложение nw.js с пользовательским URL-адресом должно быть элегантным способом. Такие как "github://", "thunder://", "twitter://"

На окнах вы можете взглянуть на:

https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx

С помощью пользовательского URL вы можете использовать простые аргументы для nw.js в режиме одного экземпляра. Увидеть:

https://github.com/nwjs/nw.js/wiki/Handling-files-and-arguments

Если требуется больше данных, может помочь base64 или даже больше методом сжатия LZ-String.

Другие вопросы по тегам