#javascript #node.js #io #child-process
#javascript #node.js #io #дочерний процесс
Вопрос:
Что я пытаюсь сделать: я написал шахматный движок на c , который я скомпилировал в исполняемый файл. Сейчас я использую Node.JS, позволяющий этому движку взаимодействовать с API шахматного веб-сайта (чтобы пользователи и другие движки могли его оспаривать).
Я использую узел. child_process
Модуль JS для создания a spawn
, который облегчит обмен данными ввода-вывода между API и движком.
Чтобы сообщить движку, что началась новая игра, я пишу "UCIn"
в процесс. Затем я жду вывода движка "id name {engine name}rnid author {my name}rnuciokrn"
. После того, как я получу этот вывод из своего движка, мне нужно "isreadyn"
будет выполнить обратную запись, чтобы позже он мог начать генерировать ходы.
Моя проблема: проблема, с которой я сталкиваюсь, заключается в том, что после моей первоначальной "UCIn"
записи в процесс я вызываю child_process.spawn().stdin.end()
. Кажется, что этот end()
вызов должен где-то существовать, иначе я, мой процесс, не улавливает ввод, который я ему пишу.
Всякий раз, когда я пытаюсь выполнить запись "isreadyn"
в дочерний процесс после получения выходных данных движка, я сталкиваюсь с этой ошибкой:
Ошибка [ERR_STREAM_WRITE_AFTER_END]: запись после завершения
Все это выглядит примерно так:
const engineExePath = 'C:\Users\chopi\Desktop\chess-engine\maestro\uci.exe';
const childProcess = require('child_process');
const spawn_options = {
cwd: null, env: null, detached: false
}
const engineStream = childProcess.spawn(engineExePath, [], spawn_options);
engineStream.stdout.on('data', function (data) {
var result = data.toString();
if (result == 'id name Maestrornid author dvdutchrnuciokrn') {
//Here, we are listening to the response from the engine, and are now ready to spit back a message to it.
//This is where the error is occurring
engineStream.stdin.write('isreadyn');
} else {
console.log('no match');
}
});
engineStream.stdin.write('ucin');
engineStream.stdin.end();
Что я пробовал: я пытался вызвать engineStream.stdin.end()
, когда дочерний процесс закрывает свой поток через:
engineStream.on('close', (code) => {
engineStream.stdin.end();
});
Однако, когда я это делаю, кажется, что между моим файлом узла и моим дочерним процессом нет никакой связи, вроде как, когда engineStream.stdin.end()
просто не вызывается вообще. Вся интеграция с этим методом будет выглядеть примерно так:
const engineExePath = 'C:\Users\chopi\Desktop\chess-engine\maestro\uci.exe';
const childProcess = require('child_process');
const spawn_options = {
cwd: null, env: null, detached: false
}
const engineStream = childProcess.spawn(engineExePath, [], spawn_options);
engineStream.stdout.on('data', function (data) {
var result = data.toString();
if (result == 'id name Maestrornid author dvdutchrnuciokrn') {
//Here, we are listening to the response from the engine, and are now ready to spit back a message to it.
engineStream.stdin.write('isreadyn');
} else {
console.log('no match');
}
});
engineStream.on('close', (code) => {
engineStream.stdin.end();
});
engineStream.stdin.write('ucin');
Что мне интересно:
Каков правильный способ облегчить этот обмен сообщениями между моим дочерним процессом и моим файлом узла?
Комментарии:
1. Работает ли это при отправке
echo uci
cmd
вместо вашего процесса? Такжеdata
не гарантируется наличие строк. ввод буферизуется в виде блоков.2. Запуск
uci.exe
, а затем вводecho uci
изcmd
ничего не возвращает. Тем не менее, я установил исполняемый файл движка в графический интерфейс шахматного движка (который передает ходы, сделанные пользователем через графический интерфейс, движку и перемещается из движка обратно к пользователю), и там он работает нормально.3. Извините, я имел в виду создание узла
cmd
вместоuci.exe
. т.е. проверка, выполняет ли другой процесс Windows так, как вы хотитеuci.exe
, или это общая проблема платформы, записывающая в стандартный набор данных из узла.4. Из быстрого теста похоже, что порожденный
cmd
может получить ввод на следующем js-тике без использования.end()
5. Вы правы,
cmd.exe
создание и повторение некоторых данных, прослушивание эха и повторная запись позволяют мне писать несколько раз. Конечно, это требует от меня удаленияengineStream.stdin.end()
. Посколькуcmd.exe
он может сделать это просто отлично, я рассмотрю причины, по которым пропуск этой строкиuci.exe
предотвратит вывод любых выходных данных в мой файл узла.