দুটি স্ট্যান্ডিন এবং স্টাডআউট বাঁধা প্রোগ্রাম


12

ধরুন আমার কাছে দুটি প্রোগ্রাম কল ProgramAএবং আছে ProgramB। আমি উভয় উইন্ডোজ সিএমডি ইন্টারপ্রেটারে একযোগে চালাতে চাই। কিন্তু আমি চাই StdOutএর ProgramAথেকে লাগানো StdInএর ProgramBএবং StdOutএর ProgramBথেকে লাগানো StdInএর ProgramA

এটার মতো কিছু

 ________________ ________________
| | | |
| StdIn (== ← === ← == (StdOut |
| প্রোগ্রাম এ | | প্রোগ্রাম বি |
| | | |
| স্টডআউট) == → === → ==) স্ট্যান্ডিন |
| ________________ | | ________________ |

এটি করার কোনও আদেশ আছে কি - সেমিডি থেকে এই কার্যকারিতাটি অর্জন করার কোনও উপায়?


4
ইউনিক্সে আমি নামী পাইপ ব্যবহার করতাম, এটি করার জন্য উইন্ডোতে নামক পাইপ নামক কিছু রয়েছে যা সম্পূর্ণ আলাদা এবং সম্ভবত প্রযোজ্য নয়।
জেসেন

@ জেসেন এখানে একটি মন্তব্য অনুসারে লিনাক্সজার্নাল.আর্টিকেল / 2156 নামক পাইপগুলি সাইগউইনের উপর কাজ করতে পারে .. যদি তাই হয় তবে আপনি প্রথমে সাইগউইনের উপর পরীক্ষার যোগ্য হলেও, উত্তর হিসাবে পোস্ট করতে পারেন
বারলোপ

আমি মনে করি প্রোগ্রামগুলিও লিখতে হবে যাতে লুপ না হয় .. সুতরাং stdout যদি খালি লাইন হয় তবে স্টিডিনকে খাওয়ান না, এবং যদি কিছু স্টিডিন না হয় তবে প্রস্থান করুন। এইভাবে একটি অসীম লুপ এড়ানো? কিন্তু আগ্রহের বাইরে আবেদন কী?
বার্লোপ

2
আপনি কি বলছেন যে "এলিজা" এর দুটি উদাহরণ থাকতে চান?
জেসেন

প্রোগ্রামগুলি হ্যান্ডল করার জন্য যদি সাবধানে ডিজাইন করা না হয় তবে তারা কোনও অচলাবস্থার মধ্যে পড়তে পারে - উভয়ই অন্যের কাছ থেকে ইনপুটটির জন্য অপেক্ষা করছে এবং কখনই কিছুই ঘটে না (বা উভয়ই পুরো বাফারগুলিতে লেখার চেষ্টা করছে এবং এগুলি খালি করার জন্য কখনই কিছু পড়েনি them )
র্যান্ডম 832

উত্তর:


5

এটি কেবল করা যায় না, এটি ব্যাচের ফাইল ছাড়া আর কিছুই করা যায় না! :-)

অস্থায়ী ফাইলটিকে "পাইপ" হিসাবে ব্যবহার করে সমস্যার সমাধান করা যেতে পারে। দ্বি নির্দেশমূলক যোগাযোগের জন্য দুটি "পাইপ" ফাইল দরকার।

প্রক্রিয়া এ "পাইপ 1" থেকে স্টিডিন পড়ে এবং "পাইপ 2" তে স্টডআউট লেখেন
প্রক্রিয়া বি "পাইপ 2" থেকে স্টিডিন পড়ে এবং "পাইপ 1" তে স্টডআউট লেখেন

উভয় ফাইল উভয়ই প্রক্রিয়া চালু করার আগেই বিদ্যমান তা গুরুত্বপূর্ণ। ফাইলগুলি শুরুতে খালি থাকতে হবে।

যদি কোনও ব্যাচ ফাইল কোনও ফাইল থেকে পড়ার চেষ্টা করে যা বর্তমান প্রান্তে ঘটে থাকে, এটি কেবল কিছুই দেয় না এবং ফাইলটি উন্মুক্ত থাকে। সুতরাং আমার রিডলাইন রুটিন অবিরাম খালি অবধি মান না পাওয়া পর্যন্ত অবিচ্ছিন্নভাবে পড়ে।

আমি একটি খালি স্ট্রিং পড়তে এবং লিখতে সক্ষম হতে চাই, তাই আমার রাইটলাইন রুটিনটি একটি অতিরিক্ত চরিত্র যুক্ত করে যা রিডলাইনটি স্ট্রিপ বন্ধ করে দেয়।

আমার A প্রক্রিয়া প্রবাহকে নিয়ন্ত্রণ করে। এটি 1 (বি কে বার্তা) লিখে জিনিসগুলি সূচনা করে এবং 10 টি পুনরাবৃত্তি সহ একটি লুপে প্রবেশ করে যেখানে এটি একটি মান (বি থেকে বার্তা) পড়ে, 1 যোগ করে এবং তারপরে ফলাফলটি লিখে দেয় (বিতে বার্তা)। অবশেষে এটি বি এর শেষ বার্তাটির জন্য অপেক্ষা করে এবং তারপরে বি কে "ছাড়ুন" বার্তা লিখে প্রস্থান করে।

আমার বি প্রক্রিয়াটি একটি শর্তসাপেক্ষে অন্তহীন লুপে রয়েছে যা একটি মান (এ থেকে বার্তা) পড়ে, 10 যোগ করে এবং তারপরে ফলাফলটি লিখে দেয় (এটিকে বার্তা)। বি যদি কখনও "ছাড়ুন" বার্তাটি পড়ে থাকে তবে তা অবিলম্বে বন্ধ হয়ে যায়।

আমি প্রদর্শন করতে চেয়েছিলাম যে যোগাযোগটি পুরোপুরি সুসংগত, সুতরাং আমি এ এবং বি উভয় প্রক্রিয়া লুপের ক্ষেত্রে একটি বিলম্বের পরিচয় দেব।

মনে রাখবেন যে রিডলাইন পদ্ধতিটি একটি শক্ত লুপে রয়েছে যা ইনপুটটির জন্য অপেক্ষা করার সময় ক্রমাগত সিপিইউ এবং ফাইল সিস্টেম উভয়কেই আপত্তিজনকভাবে ব্যবহার করে। লিংকে একটি পিং বিলম্ব যোগ করা যেতে পারে তবে প্রক্রিয়াগুলি তেমন প্রতিক্রিয়াশীল হবে না।

আমি এ এবং বি উভয় প্রসেস চালু করার সুবিধার্থে একটি সত্য পাইপ ব্যবহার করি। তবে পাইপটি অ-কার্যকরী যে কোনও যোগাযোগ এটির মধ্য দিয়ে যায় না। সমস্ত যোগাযোগ আমার অস্থায়ী "পাইপ" ফাইলগুলির মাধ্যমে।

প্রক্রিয়াগুলি আরম্ভ করার জন্য আমি শুরু / বি ব্যবহার করতে পারতাম, তবে তখন আমি তাদের উভয়টি সমাপ্ত হওয়ার সময় সনাক্ত করতে পারি যাতে অস্থায়ী "পাইপ" ফাইলগুলি কখন মুছতে হয় তা আমি জানতে পারি। পাইপটি ব্যবহার করা অনেক সহজ।

আমি সমস্ত কোডকে একটি ফাইলে রেখে দিতে বেছে নিয়েছি - মাস্টার স্ক্রিপ্ট যা 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

--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 ব্যবহার করে এমন একটি উদাহরণ দেওয়া আছে। প্রক্রিয়াগুলি চালু করতে আমি এখনও ব্যাচ ব্যবহার করি। আমি এখানে বর্ণিত একটি খুব শীতল পদ্ধতি ব্যবহার করছি অস্থায়ী ফাইলটি ব্যবহার না করে কোনও ব্যাচ ফাইলের মধ্যে ভিবিএস স্ক্রিপ্ট এম্বেড এবং সম্পাদন করা সম্ভব? একক ব্যাচের স্ক্রিপ্টের মধ্যে একাধিক ভিবিএস স্ক্রিপ্টগুলি এম্বেড করতে।

ভিবিএসের মতো উচ্চতর ভাষার সাথে, আমরা এ থেকে বি তে তথ্য পাস করার জন্য একটি সাধারণ পাইপ ব্যবহার করতে পারি, খ থেকে বি থেকে ক এ তথ্য পাঠানোর জন্য আমাদের কেবলমাত্র একটি অস্থায়ী "পাইপ" ফাইলের প্রয়োজন কারণ আমাদের এখন একটি কার্যকরী পাইপ রয়েছে, এ প্রক্রিয়াটি বিতে "ছাড়ুন" বার্তা প্রেরণের প্রয়োজন হয় না বি-প্রক্রিয়াটি কেবল ফাইল-এর শেষ না হওয়া অবধি লুপ হয়।

এটি নিশ্চিত যে ভিবিএসে একটি সঠিক ঘুমের ক্রিয়ায় অ্যাক্সেস করা ভাল having এটি আমাকে সিপিইউকে বিরতি দেওয়ার জন্য রিডলাইন ফাংশনটিতে খুব সহজেই একটি সংক্ষিপ্ত বিলম্ব প্রবর্তন করতে সক্ষম করে।

যাইহোক, রিডলিনের মধ্যে একটি চুলকানি রয়েছে। প্রথমে আমি মাঝে মাঝে মাঝে ব্যর্থতা পাচ্ছিলাম যতক্ষণ না আমি বুঝতে পারি যে কখনও কখনও রিডলাইন স্টিডিনে তথ্য উপলব্ধ থাকে এবং বিটি লাইনটি লেখার কাজ শেষ করার আগে অবিলম্বে লাইনটি পড়ার চেষ্টা করবে। ফাইল-এর শেষে পরীক্ষা এবং পড়ার মধ্যে একটি সংক্ষিপ্ত বিলম্ব প্রবর্তন করে আমি সমস্যার সমাধান করেছি। 5 এমসেকের বিলম্বটি আমার পক্ষে কৌশলটি করেছে বলে মনে হয়েছিল, তবে আমি নিরাপদ দিকে থাকতে 10 ম্যাসকে দ্বিগুণ করেছি। এটি খুব আকর্ষণীয় যে ব্যাচ এই সমস্যাটি ভোগ করে না। আমরা 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>

খাঁটি ব্যাচের সমাধানের সাথে আউটপুট একই, চূড়ান্ত "প্রস্থান" রেখাগুলি না থাকলে।


4

দ্রষ্টব্য- বিপরীতমুখী, আবার প্রশ্ন পড়া, এটি জিজ্ঞাসা করা হয় না। যেহেতু, এটি দুটি প্রক্রিয়া একসাথে লিঙ্ক করার সময়, (একটি আকর্ষণীয় উপায়ে যা এমনকি কোনও নেটওয়ার্কেও কাজ করে!), এটি উভয়ভাবেই লিঙ্ক করে না।


আমি আশা করি আপনি এর কয়েকটি উত্তর পেয়ে যাবেন।

এখানে আমার উত্তর কিন্তু এটি গ্রহণ করবেন না, অন্যান্য উত্তরের জন্য অপেক্ষা করুন, আমি আরও কিছু উত্তর দেখার জন্য আগ্রহী।

এটি সাইগউইন থেকে করা হয়েছিল। এবং 'এনসি' কমান্ড ব্যবহার করে (চালাকটি)। 'ডাব্লুসি-এল' কেবল লাইন গণনা করে। সুতরাং আমি এনসি ব্যবহার করে ইকো এবং ডাব্লিউসি, দুটি ক্ষেত্রেই এই দুটি কমান্ডকে যুক্ত করছি।

বাম দিকের কমান্ডটি প্রথমে করা হয়েছিল।

এনসি হ'ল একটি কমান্ড যা ক) একটি সার্ভার তৈরি করতে বা খ) কাঁচা মোডে টেলনেট কমান্ডের মতো সার্ভারের সাথে সংযোগ স্থাপন করতে সক্ষম। আমি বাম কমান্ডে 'a' ব্যবহার এবং ডান কমান্ডে 'বি' ব্যবহার করছি।

এনসি সেখানে বসে একটি ইনপুটটির জন্য অপেক্ষা করে বসেছিল এবং তারপরে সেই পাইপটি wc -lলাইনগুলিতে ইনপুট করে এবং ইনপুটযুক্ত লাইনের সংখ্যা নির্ধারণ করে।

তারপরে আমি কিছু পাঠ্য প্রতিধ্বনি করতে লাইনটি চালিয়েছি এবং সেই কাঁচাটিকে 127.0.0.1ব্দ23 এ পাঠিয়েছি যা উল্লিখিত সার্ভার।

এখানে চিত্র বর্ণনা লিখুন

আপনি সাইগউইন থেকে nc.exe কমান্ড অনুলিপি করতে পারেন এবং একই ডিরেক্টরিতে এটি প্রয়োজন যে cygwin1.dll ফাইল ব্যবহার করার চেষ্টা করতে পারেন। অথবা আপনি আমার মতো সাইগউইন থেকে এটি করতে পারেন। আমি gnuwin32 এ nc.exe দেখতে পাচ্ছি না। তাদের একটি অনুসন্ধান আছে http://gnuwin32.sourceforge.net/ এবং এনসি বা নেটকাট আসে না। তবে আপনি সাইগউইন https://cygwin.com/install.html পেতে পারেন


এটি কী হতে চলেছে তা বোঝার আগে এটি পড়তে আমার দশবার মতো সময় লেগেছে ..... বরং চতুর
দারথরবিক

@ দারথরবিক হ্যাঁ, এবং আপনি netstat -aon | find ":123"দেখতে পারেন যে বাম দিকের কমান্ডটি সার্ভার তৈরি করেছে
বার্লপ

তবে আপনি কীভাবে অন্য দিকটি যোগাযোগ করেন (যেমন কমান্ডের wcপিছন থেকে echo)।
দারথরবিক

যখন আমি এনসি দিয়ে এটি উভয় উপায়ে করার চেষ্টা করি তখন আমি এটি কাজ করতে পারি না, সম্ভবত এনসি কোনও ধরণের লুপে চলে যায়।
বার্লোপ

nc -lp9999 | prog1 | prog2 | nc 127.0.0.1 9999সময়মতো বাফারগুলি ফ্লাশ করা হয় তা নিশ্চিত করার জন্য পদক্ষেপগুলি গ্রহণ করা প্রয়োজন
জেসেন

2

একটি হ্যাক (আমি এটি না করাকে পছন্দ করব, তবে এটি এখনই যাচ্ছি) আপনার জন্য এটি করার জন্য একটি সি # অ্যাপ্লিকেশন লিখতে হবে। আমি এই প্রোগ্রামটিতে কিছু মূল বৈশিষ্ট্য প্রয়োগ করি নি (যেমন আসলে আমাকে প্রদত্ত যুক্তিগুলি ব্যবহার করে), তবে এখানে এটি রয়েছে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;


namespace Joiner
{
    class Program
    {
        static Process A;
        static Process B;
        static void AOutputted(object s, DataReceivedEventArgs a)
        {
            Console.WriteLine("A:" + a.Data);
            //Console.WriteLine("Sending to B");
            B.StandardInput.WriteLine(a.Data);
        }
        static void BOutputted(object s, DataReceivedEventArgs a)
        {
            Console.WriteLine("B:" + a.Data);
            //Console.WriteLine("Sending to A");
            A.StandardInput.WriteLine(a.Data);
        }
        static void Main(string[] args)
        {

            A = new Process();
            B = new Process();
            A.StartInfo.FileName = "help";
            B.StartInfo.FileName = "C:\\Users\\Owner\\Documents\\Visual Studio 2010\\Projects\\Joiner\\Test\\bin\\Debug\\Test.exe";

            A.StartInfo.Arguments = "mkdir";
            //B.StartInfo.Arguments = "/E /K type CON";

            A.StartInfo.UseShellExecute = false;
            B.StartInfo.UseShellExecute = false;

            A.StartInfo.RedirectStandardOutput = true;
            B.StartInfo.RedirectStandardOutput = true;

            A.StartInfo.RedirectStandardInput = true;
            B.StartInfo.RedirectStandardInput = true;

            A.OutputDataReceived += AOutputted;
            B.OutputDataReceived += BOutputted;

            A.Start();
            B.Start();

            A.BeginOutputReadLine();
            B.BeginOutputReadLine();



            while (!A.HasExited || !B.HasExited) { }
            Console.ReadLine();

        }
    }
}

তারপরে অবশেষে, যখন এই প্রোগ্রামটি সম্পূর্ণরূপে কার্যকরী হয় এবং ডিবাগ কোডটি সরানো হয় আপনি এ জাতীয় কিছু ব্যবহার করবেন:

joiner "A A's args" "B B's Args"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.