Tidak hanya itu bisa dilakukan, itu bisa dilakukan dengan apa-apa selain file batch! :-)
Masalahnya dapat diselesaikan dengan menggunakan file sementara sebagai "pipa". Komunikasi dua arah memerlukan dua file "pipa".
Proses A membaca stdin dari "pipe1" dan menulis stdout ke "pipe2"
Proses B membaca stdin dari "pipe2" dan menulis stdout ke "pipe1"
Penting bahwa kedua file ada sebelum meluncurkan proses mana pun. File harus kosong di awal.
Jika file batch mencoba membaca dari file yang kebetulan berada di akhir saat ini, itu hanya mengembalikan apa-apa, dan file tetap terbuka. Jadi rutin readLine saya terus membaca hingga mendapat nilai yang tidak kosong.
Saya ingin dapat membaca dan menulis string kosong, jadi rutinitas writeLine saya menambahkan karakter tambahan yang strip readLine lepas.
Proses A saya mengontrol aliran. Ini memulai sesuatu dengan menulis 1 (pesan ke B), dan kemudian memasuki satu lingkaran dengan 10 iterasi di mana ia membaca nilai (pesan dari B), menambahkan 1, dan kemudian menulis hasilnya (pesan ke B). Akhirnya ia menunggu pesan terakhir dari B, dan kemudian menulis pesan "keluar" ke B dan keluar.
Proses B saya berada dalam loop tanpa syarat bersyarat yang membaca nilai (pesan dari A), menambahkan 10, dan kemudian menulis hasilnya (pesan ke A). Jika B pernah membaca pesan "keluar", maka itu segera berakhir.
Saya ingin menunjukkan bahwa komunikasi sepenuhnya sinkron, jadi saya memperkenalkan penundaan pada loop proses A dan B.
Perhatikan bahwa prosedur readLine dalam loop ketat yang terus-menerus menyalahgunakan CPU dan sistem file sambil menunggu input. Penundaan PING dapat ditambahkan ke loop, tetapi kemudian proses tidak akan responsif.
Saya menggunakan pipa sejati sebagai kemudahan untuk meluncurkan proses A dan B. Tetapi pipa itu tidak berfungsi karena tidak ada komunikasi yang melewatinya. Semua komunikasi adalah melalui file "pipa" sementara saya.
Saya bisa saja menggunakan START / B untuk meluncurkan proses, tetapi kemudian saya harus mendeteksi kapan keduanya berakhir sehingga saya tahu kapan harus menghapus file "pipa" sementara. Jauh lebih mudah menggunakan pipa.
Saya memilih untuk meletakkan semua kode dalam satu file - skrip master yang meluncurkan A dan B, serta kode untuk A dan B. Saya bisa menggunakan file skrip terpisah untuk setiap proses.
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
--KELUARAN--
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
Hidup sedikit lebih mudah dengan bahasa tingkat yang lebih tinggi. Di bawah ini adalah contoh yang menggunakan VBScript untuk proses A dan B. Saya masih menggunakan batch untuk meluncurkan proses. Saya menggunakan metode yang sangat keren yang dijelaskan di Mungkinkah menanamkan dan mengeksekusi VBScript dalam file batch tanpa menggunakan file sementara? untuk menanamkan beberapa skrip VBS dalam skrip batch tunggal.
Dengan bahasa yang lebih tinggi seperti VBS, kita dapat menggunakan pipa normal untuk meneruskan info dari A ke B. Kita hanya perlu satu file "pipa" sementara untuk meneruskan info dari B kembali ke A. Karena kita sekarang memiliki pipa yang berfungsi, A proses tidak perlu mengirim pesan "berhenti" ke B. Proses B hanya loop sampai mencapai akhir file.
Memang menyenangkan memiliki akses ke fungsi tidur yang tepat di VBS. Ini memungkinkan saya untuk dengan mudah memperkenalkan penundaan singkat pada fungsi readLine untuk memberikan CPU istirahat.
Namun, ada satu kerutan di dalam readLIne. Pada awalnya saya mendapatkan kegagalan yang terputus-putus sampai saya menyadari bahwa kadang-kadang readLine akan mendeteksi informasi tersedia di stdin, dan akan segera mencoba membaca baris sebelum B memiliki kesempatan untuk menyelesaikan penulisan baris. Saya memecahkan masalah dengan memperkenalkan penundaan singkat antara tes akhir file dan membaca. Penundaan 5 msec tampaknya melakukan trik untuk saya, tetapi saya menggandakannya menjadi 10 msec hanya untuk berada di sisi yang aman. Sangat menarik bahwa batch tidak mengalami masalah ini. Kami membahas ini secara singkat (5 pos pendek) di http://www.dostips.com/forum/viewtopic.php?f=3&t=7078#p47432 .
<!-- : 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>
Outputnya sama dengan solusi batch murni, kecuali baris "berhenti" akhir tidak ada.