简体   繁体   English

控制台应用程序相互通信的推荐方式是什么?

[英]What's the recommended way for console applications to talk with each other?

I got a system of console applications written in C# running on different machines. 我有一个用C#编写的控制台应用程序系统,在不同的计算机上运行。 I use MSMQ. 我使用MSMQ。

My questions is, how do I make my console applications communicate to each other? 我的问题是,如何使控制台应用程序彼此通信?

I'm asking because I want to create a new console application that can be queried by other applications to know the number of messages in MSMQ. 我之所以问是因为我想创建一个新的控制台应用程序,其他应用程序可以查询该应用程序以了解MSMQ中的消息数。

Edit 1: Thanks for the replies and comments! 编辑1:感谢您的答复和评论! About the requirements, I'm estimating maybe about 10-50/sec of queries 关于需求,我估计大约每秒10-50次查询

You need to use a pipe to achieve this: see Named pipe and anonymous pipe 您需要使用管道来实现此目的:请参阅命名管道和匿名管道

A pipe works like this: The host application (the one launching the console application) has to create a pipe to catch the concole application's std output and an other one to write to the console application's std input. 管道的工作方式如下:主机应用程序(一个启动控制台应用程序)必须创建一个管道,以捕获conconle应用程序的std输出,而另一个则写入控制台应用程序的std输入。

There is plenty of code example in the link I gave you 我给您的链接中有很多代码示例

Also here is a code example (using existing pipes StandardInput and StandardOutput): it starts a cmd.exe console but it is a layer over: not the actual console...see for yourself: 这也是一个代码示例(使用现有管道StandardInput和StandardOutput):它启动cmd.exe控制台,但它位于上面:不是实际的控制台...亲自体验:

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

namespace ConsoleApplication1
{
    class Program
    {
        private static StreamReader reader;

        static void Main(string[] args)
        {
            Process cmd = new Process();

            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.UseShellExecute = false;

            cmd.Start();

            reader = cmd.StandardOutput;
            StreamWriter writer = cmd.StandardInput;


            Thread t = new Thread(new ThreadStart(writingThread));

            t.Start();

            //Just write everything we type to the cmd.exe process
            while (true) writer.Write((char)Console.Read());

        }

        public static void writingThread()
        {
            //Just write everything cmd.exe writes back to our console
            while (true) Console.Write((char)reader.Read());
        }
    }
}

You can achieve the same result by replacing the StreamReader and the StreamWriter by a port connection (socket) buffer for remote communication between two process http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx 通过用端口连接(套接字)缓冲区替换StreamReader和StreamWriter(用于两个进程之间的远程通信),可以实现相同的结果http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket的.aspx

It is recommended to secure the communication to minimize intrusion possibility 建议确保通信安全,以最大程度地减少入侵的可能性

Here is an example of communication through a sockets...now this is running in one program but everything is on separate threads and it would work if the communication was to be on two separate machines: the server is the one controlling the process cmd.exe and the client is a viewer/writer 这是一个通过套接字进行通信的示例...现在,该通信正在一个程序中运行,但是所有操作都在单独的线程上,并且如果通信要在两台不同的计算机上进行,它将可以正常工作:服务器是控制进程cmd的服务器。 exe,客户端是查看器/编写器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        private static StreamReader reader;
        private static StreamWriter writer;

        static void Main(string[] args)
        {
            //Server initialisation 

            Process cmdServer = new Process();

            cmdServer.StartInfo.FileName = "cmd.exe";
            cmdServer.StartInfo.RedirectStandardInput = true;
            cmdServer.StartInfo.RedirectStandardOutput = true;
            cmdServer.StartInfo.UseShellExecute = false;

            cmdServer.Start();

            reader = cmdServer.StandardOutput;
            writer = cmdServer.StandardInput;


            Thread t1 = new Thread(new ThreadStart(clientListener));
            t1.Start();
            Thread t2 = new Thread(new ThreadStart(clientWriter));
            t2.Start();
            Thread t3 = new Thread(new ThreadStart(serverListener));
            t3.Start();
            Thread t4 = new Thread(new ThreadStart(serverWriter));
            t4.Start();


        }

        public static void clientWriter()
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            Int32 size = 0;
            Byte[] buff = new Byte[1024];

            sock.Connect(IPAddress.Parse("127.0.0.1"), 4357);
            Console.WriteLine("clientWriter connected");

            while (true)
            {
                String line = Console.ReadLine();
                line += "\n";
                Char[] chars = line.ToArray();
                size = chars.Length;
                if (size > 0)
                {
                    buff = Encoding.Default.GetBytes(chars);
                    //Console.WriteLine("Sending \"" + new String(chars, 0, size) + "\"");
                    sock.Send(buff, size, 0);
                }
            }
        }

        /// <summary>
        /// Local client that listens to what the server sends on port 4356
        /// </summary>
        public static void clientListener()
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sock.Bind(new IPEndPoint(IPAddress.Any, 4356));
            sock.Listen(0);

            Int32 size = 0;
            Byte[] buff = new Byte[1024];
            Char[] cbuff = new Char[1024];

            while (true)
            {
                Console.WriteLine("clientListener Waiting for connection");
                sock = sock.Accept();
                Console.WriteLine("clientListener Connection accepted " + ((sock.Connected)?"Connected" : "Not Connected"));

                while ((size = sock.Receive(buff)) > 0)
                {
                    for (int i = 0; i < size; i++) cbuff[i] = (Char)buff[i];
                    Console.Write(cbuff, 0, size);
                }

                sock.Close();

            }
        }

        /// <summary>
        /// Remote server that listens to what the client sends on port 4357
        /// </summary>
        public static void serverListener()
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sock.Bind(new IPEndPoint(IPAddress.Any, 4357));
            sock.Listen(0);

            Int32 size = 0;
            Byte[] buff = new Byte[1024];
            Char[] cbuff = new Char[1024];

            while (true)
            {
                Console.WriteLine("serverListener Waiting for connection");
                sock = sock.Accept();
                Console.WriteLine("serverListener Connection accepted " + ((sock.Connected) ? "Connected" : "Not Connected"));

                while ((size = sock.Receive(buff)) > 0)
                {
                    for (int i = 0; i < size; i++) cbuff[i] = (Char)buff[i];
                    //Console.WriteLine("Received \"" + new String(cbuff,0,size) + "\"");
                    writer.Write(cbuff, 0, size);
                }

            }
        }

        /// <summary>
        /// Remote server that writes the output of the colsole application through the socket
        /// </summary>
        public static void serverWriter()
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            Int32 size = 0;
            Byte[] buff = new Byte[1024];
            Char[] cbuff = new Char[1024];

            sock.Connect(IPAddress.Parse("127.0.0.1"), 4356);

            Console.WriteLine("serverWriter connected");

            while (true)
            {
                size = reader.Read(cbuff, 0, 1024);
                if (size > 0)
                {
                    for (int i = 0; i < size; i++) buff[i] = (Byte)cbuff[i];
                    sock.Send(buff, 0, size, 0);
                }
            }
        }
    }
}

testable and extendable - can be easily changed to work between computers. 可测试和可扩展-可以轻松更改以在计算机之间工作。

you have a few methods. 您有几种方法。 "named pipes" can be achieved easily using WCF. 使用WCF可以轻松实现“命名管道”。 its nice because its very testable. 它很好,因为它非常容易测试。

best performance you can use memory mapped files http://weblogs.asp.net/gunnarpeipman/archive/2009/06/21/net-framework-4-0-using-memory-mapped-files.aspx 可以使用内存映射文件获得最佳性能 http://weblogs.asp.net/gunnarpeipman/archive/2009/06/21/net-framework-4-0-using-memory-mapped-files.aspx

they have AMAZING performance. 他们有惊人的表现。 BUT less harder to test. 但是较难测试。

easiest - if you have very low traffic you can use the registry. 最简单 -如果流量很小,则可以使用注册表。 theres a Regisrty class in C# its threadsafe and fast. C#中有一个Regisrty类,它的线程安全且快速。

WCF. WCF。 WCF, WCF, WCF, WCF. WCF,WCF,WCF,WCF。

Don't bother reinventing the wheel, just use WCF for communications, and let it worry about the details (whether using a pipe or some other mechanism). 不必费心改造轮子,只需使用WCF进行通信,并让它担心细节(无论是使用管道还是其他机制)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM