그것은 할 수있을뿐만 아니라 배치 파일만으로 할 수 있습니다! :-)
임시 파일을 "파이프"로 사용하면이 문제를 해결할 수 있습니다. 양방향 통신에는 두 개의 "파이프"파일이 필요합니다.
프로세스 A는 "pipe1"에서 stdin을 읽고 stdout을 "pipe2"에 씁니다.
프로세스 B는 "pipe2"에서 stdin을 읽고 stdout를 "pipe1"에 씁니다.
프로세스를 시작하기 전에 두 파일이 모두 존재해야합니다. 시작시 파일이 비어 있어야합니다.
배치 파일이 현재 끝에있는 파일에서 읽으려고하면 아무 것도 반환하지 않고 파일은 열린 상태로 유지됩니다. 따라서 내 readLine 루틴은 비어 있지 않은 값을 얻을 때까지 지속적으로 읽습니다.
빈 문자열을 읽고 쓸 수 있기를 원하므로 writeLine 루틴이 readLine이 제거하는 추가 문자를 추가합니다.
내 A 프로세스는 흐름을 제어합니다. 1 (메시지 B에 메시지)을 작성하여 일을 시작한 다음 10 개의 반복으로 루프를 시작하여 값 (B의 메시지)을 읽고 1을 추가 한 다음 결과를 씁니다 (메시지 B). 마지막으로 B에서 마지막 메시지를 기다린 다음 "quit"메시지를 B에 쓰고 종료합니다.
내 B 프로세스는 값 (A의 메시지)을 읽고 10을 더한 다음 결과를 (메시지 A) 쓰는 조건부 끝없는 루프에 있습니다. B가 "quit"메시지를 읽으면 즉시 종료됩니다.
통신이 완전히 동기화되어 있음을 증명하고 싶었으므로 A 및 B 프로세스 루프 모두에서 지연이 발생했습니다.
readLine 프로시 저는 입력을 기다리는 동안 CPU와 파일 시스템을 지속적으로 악용하는 긴밀한 루프 상태입니다. 루프에 PING 지연을 추가 할 수 있지만 프로세스가 응답하지 않습니다.
A와 B 프로세스를 모두 시작하기 위해 편의상 진정한 파이프를 사용합니다. 그러나 파이프가 통신을 통과하지 않는다는 점에서 파이프가 작동하지 않습니다. 모든 통신은 임시 "파이프"파일을 통해 이루어집니다.
프로세스를 시작하기 위해 START / B를 사용할 수도 있었지만 임시 "파이프"파일을 삭제할시기를 알 수 있도록 프로세스가 모두 종료되는 시점을 감지해야했습니다. 파이프를 사용하는 것이 훨씬 간단합니다.
모든 코드를 단일 파일 (A 및 B를 시작하는 마스터 스크립트와 A 및 B 용 코드)에 넣기로 결정했습니다. 각 프로세스마다 별도의 스크립트 파일을 사용할 수있었습니다.
test.bat
@echo off
if "%~1" equ "" (
copy nul pipe1.txt >nul
copy nul pipe2.txt >nul
"%~f0" A <pipe1.txt >>pipe2.txt | "%~f0" B <pipe2.txt >>pipe1.txt
del pipe1.txt pipe2.txt
exit /b
)
setlocal enableDelayedExpansion
set "prog=%~1"
goto !prog!
:A
call :writeLine 1
for /l %%N in (1 1 5) do (
call :readLine
set /a ln+=1
call :delay 1
call :writeLine !ln!
)
call :readLine
call :delay 1
call :writeLine quit
exit /b
:B
call :readLine
if !ln! equ quit exit /b
call :delay 1
set /a ln+=10
call :writeLine !ln!
goto :B
:readLine
set "ln="
set /p "ln="
if not defined ln goto :readLine
set "ln=!ln:~0,-1!"
>&2 echo !prog! reads !ln!
exit /b
:writeLine
>&2 echo !prog! writes %*
echo(%*.
exit /b
:delay
setlocal
set /a cnt=%1+1
ping localhost /n %cnt% >nul
exit /b
--산출--
C:\test>test
A writes 1
B reads 1
B writes 11
A reads 11
A writes 12
B reads 12
B writes 22
A reads 22
A writes 23
B reads 23
B writes 33
A reads 33
A writes 34
B reads 34
B writes 44
A reads 44
A writes 45
B reads 45
B writes 55
A reads 55
A writes 56
B reads 56
B writes 66
A reads 66
A writes quit
B reads quit
더 높은 수준의 언어로 인생은 조금 더 쉽습니다. 아래는 A 및 B 프로세스에 VBScript를 사용하는 예입니다. 여전히 배치를 사용하여 프로세스를 시작합니다. 임시 파일을 사용하지 않고 배치 파일 내에 VBScript를 포함하고 실행할 수 있습니까?에 설명 된 매우 멋진 방법 을 사용합니다. 단일 배치 스크립트 내에 여러 VBS 스크립트를 포함합니다.
VBS와 같은 더 높은 언어를 사용하면 일반 파이프를 사용하여 A에서 B로 정보를 전달할 수 있습니다. B에서 A로 정보를 다시 전달하려면 하나의 임시 "파이프"파일 만 있으면됩니다. 이제 기능 파이프 인 A가 있으므로 프로세스는 "quit"메시지를 B로 보낼 필요가 없습니다. B 프로세스는 파일 끝에 도달 할 때까지 단순히 루프됩니다.
VBS에서 적절한 절전 기능에 액세스하는 것이 좋습니다. 이렇게하면 readLine 함수에 짧은 지연을 쉽게 도입하여 CPU가 중단 될 수 있습니다.
그러나 readLIne 내에 하나의 주름이 있습니다. 처음에는 때때로 readLine이 stdin에서 정보를 사용할 수 있음을 발견하고 B가 줄 쓰기를 마치기 전에 즉시 줄을 읽으려고 할 때까지 간헐적 오류가 발생했습니다. 파일 끝 테스트와 읽기 사이에 짧은 지연을 도입하여 문제를 해결했습니다. 5msec의 지연은 나를 위해 속임수처럼 보이지만, 나는 안전한면에 있기 위해 10msec로 두 배로 늘 렸습니다. 배치가이 문제를 겪지 않는다는 것은 매우 흥미 롭습니다. 우리는 http://www.dostips.com/forum/viewtopic.php?f=3&t=7078#p47432 에서 간략하게 (5 개의 짧은 게시물) 토론했습니다 .
<!-- : Begin batch script
@echo off
copy nul pipe.txt >nul
cscript //nologo "%~f0?.wsf" //job:A <pipe.txt | cscript //nologo "%~f0?.wsf" //job:B >>pipe.txt
del pipe.txt
exit /b
----- Begin wsf script --->
<package>
<job id="A"><script language="VBS">
dim ln, n, i
writeLine 1
for i=1 to 5
ln = readLine
WScript.Sleep 1000
writeLine CInt(ln)+1
next
ln = readLine
function readLine
do
if not WScript.stdin.AtEndOfStream then
WScript.Sleep 10 ' Pause a bit to let B finish writing the line
readLine = WScript.stdin.ReadLine
WScript.stderr.WriteLine "A reads " & readLine
exit function
end if
WScript.Sleep 10 ' This pause is to give the CPU a break
loop
end function
sub writeLine( msg )
WScript.stderr.WriteLine "A writes " & msg
WScript.stdout.WriteLine msg
end sub
</script></job>
<job id="B"> <script language="VBS">
dim ln, n
do while not WScript.stdin.AtEndOfStream
ln = WScript.stdin.ReadLine
WScript.stderr.WriteLine "B reads " & ln
n = CInt(ln)+10
WScript.Sleep 1000
WScript.stderr.WriteLine "B writes " & n
WScript.stdout.WriteLine n
loop
</script></job>
</package>
최종 "quit"라인이 없다는 점을 제외하면 출력은 순수한 배치 솔루션과 동일합니다.