न केवल यह किया जा सकता है, यह एक बैच फ़ाइल के अलावा कुछ भी नहीं किया जा सकता है! :-)
"पाइप" के रूप में एक अस्थायी फ़ाइल का उपयोग करके समस्या को हल किया जा सकता है। द्विदिश संचार को दो "पाइप" फाइलों की आवश्यकता होती है।
प्रोसेस A स्टड को "पाइप 1" से पढ़ता है और "पाइप 2" को stdout लिखता है।
प्रोसेस बी "पाइप 2" से स्टड को पढ़ता है और "पाइप 1" को स्टडआउट लिखता है
यह महत्वपूर्ण है कि दोनों फाइलें या तो प्रक्रिया शुरू करने से पहले मौजूद हों। फाइलें शुरू में खाली होनी चाहिए।
यदि बैच फ़ाइल वर्तमान छोर पर होने वाली फ़ाइल से पढ़ने का प्रयास करती है, तो यह बस कुछ भी नहीं लौटाती है, और फ़ाइल खुली रहती है। इसलिए मेरी रीडलाइन नियमित रूप से लगातार पढ़ती है जब तक कि यह एक गैर-रिक्त मान न हो जाए।
मैं एक खाली स्ट्रिंग को पढ़ने और लिखने में सक्षम होना चाहता हूं, इसलिए मेरी राइटलाइन रूटीन में एक अतिरिक्त चरित्र है जो कि रीडलाइन स्ट्रिप्स को बंद कर देता है।
मेरी A प्रक्रिया प्रवाह को नियंत्रित करती है। यह 1 (बी को संदेश) लिखकर चीजें शुरू करता है, और फिर 10 पुनरावृत्तियों के साथ एक लूप में प्रवेश करता है जहां यह एक मूल्य (बी से संदेश) पढ़ता है, 1 जोड़ता है, और फिर परिणाम (बी को संदेश) लिखता है। अंत में यह B के अंतिम संदेश की प्रतीक्षा करता है, और फिर B को एक "छोड़" संदेश लिखता है और बाहर निकलता है।
मेरी बी प्रक्रिया एक सशर्त अंतहीन लूप में है जो एक मान (ए से संदेश) पढ़ता है, 10 जोड़ता है, और फिर परिणाम (ए को संदेश) लिखता है। यदि बी कभी "छोड़" संदेश पढ़ता है, तो यह तुरंत समाप्त हो जाता है।
मैं प्रदर्शित करना चाहता था कि संचार पूरी तरह से समकालिक है, इसलिए मैं ए और बी दोनों प्रक्रिया लूप में देरी का परिचय देता हूं।
ध्यान दें कि readLine प्रक्रिया एक तंग लूप में है जो इनपुट के लिए प्रतीक्षा करते समय सीपीयू और फाइल सिस्टम दोनों को लगातार गाली देती है। एक पिंग देरी को लूप में जोड़ा जा सकता है, लेकिन फिर प्रक्रियाएं उतने उत्तरदायी नहीं होंगी।
मैं ए और बी दोनों प्रक्रियाओं को लॉन्च करने के लिए एक सुविधा के रूप में एक सच्चे पाइप का उपयोग करता हूं। लेकिन पाइप गैर-कार्यात्मक है कि कोई संचार इसके माध्यम से नहीं गुजरता है। सभी संचार मेरी अस्थायी "पाइप" फाइलों के माध्यम से है।
मैं प्रक्रियाओं को लॉन्च करने के लिए बस START / 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
--OUTPUT--
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 स्क्रिप्ट एम्बेड करने के लिए।
वीबीएस जैसी उच्च भाषा के साथ, हम ए से बी तक जानकारी पास करने के लिए एक सामान्य पाइप का उपयोग कर सकते हैं। हमें बी से ए तक जानकारी पास करने के लिए केवल एक अस्थायी "पाइप" फ़ाइल की आवश्यकता है क्योंकि हमारे पास अब एक कार्यशील पाइप है, ए। प्रक्रिया को बी के लिए एक "छोड़ दिया" संदेश भेजने की आवश्यकता नहीं है। बी प्रक्रिया बस छोरों तक जाती है जब तक कि यह फ़ाइल के अंत तक नहीं पहुंचती।
यह निश्चित है कि वीबीएस में एक उचित नींद समारोह के लिए उपयोग करना अच्छा है। यह मुझे सीपीयू को ब्रेक देने के लिए रीडलाइन फ़ंक्शन में आसानी से एक छोटी देरी शुरू करने में सक्षम बनाता है।
हालाँकि, readLIne के भीतर एक शिकन है। पहले तो मुझे रुक-रुक कर असफलताएँ मिल रही थीं, जब तक मुझे एहसास नहीं हो गया था कि कभी-कभी रीडलाइन पता लगा लेगी कि जानकारी स्टड पर उपलब्ध है, और तुरंत बी को लाइन लिखने का मौका देने से पहले लाइन को पढ़ने की कोशिश करेंगे। मैंने एंड-ऑफ़-फ़ाइल परीक्षण और रीड के बीच एक छोटी देरी की शुरुआत करके समस्या को हल किया। 5 मिसे की देरी से मेरे लिए चाल चल रही थी, लेकिन मुझे दोगुना हो गया कि 10 मिसेक सिर्फ सुरक्षित पक्ष में होना चाहिए। यह बहुत दिलचस्प है कि बैच को इस मुद्दे का सामना नहीं करना पड़ता है। हमने इस बारे में 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>
आउटपुट शुद्ध बैच समाधान के साथ ही है, अंतिम "छोड़" लाइनों के अलावा नहीं हैं।