2

我希望能够在服务器应用程序和客户端应用程序之间进行通信。这两个应用程序都是用 C#/WPF 编写的。接口位于一个单独的 DLL 中,两个应用程序都引用它。

在 interface-dll 中是 IDataInfo-Interface,它看起来像:

public interface IDataInfo
    {
        byte[] Header { get; }
        byte[] Data { get; }
    }

服务器应用程序通过以下代码调用客户端:

Serializer<IDataInfo> serializer = new Serializer<IDataInfo>();
IDataInfo dataInfo = new DataInfo(HEADERBYTES, CONTENTBYTES);
Process clientProcess = Process.Start("Client.exe", serializer.Serialize(dataInfo));

客户端应用程序通过以下方式从服务器获取消息:

Serializer<IDataInfo> serializer = new Serializer<IDataInfo>();
IDataInfo dataInfo = serializer.Deserialize(string.Join(" ", App.Args));

Serializer-Class 只是一个通用类,它使用 Soap-Formatter 来序列化/反序列化。代码如下所示:

public class Serializer<T>
{
    private static readonly Encoding encoding = Encoding.Unicode;

    public string Serialize(T value)
    {
        string result;
        using (MemoryStream memoryStream = new MemoryStream())
        {
            SoapFormatter soapFormatter = new SoapFormatter();
            soapFormatter.Serialize(memoryStream, value);
            result = encoding.GetString(memoryStream.ToArray());
            memoryStream.Flush();
        }
        return result;
    }

    public T Deserialize(string soap)
    {
        T result;
        using (MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(soap)))
        {
            SoapFormatter soapFormatter = new SoapFormatter();
            result = (T)soapFormatter.Deserialize(memoryStream);
        }
        return result;
    }
}

直到这里一切正常。服务器创建客户端,客户端可以将它的参数反序列化到IDataInfo-Object。

现在我希望能够从服务器向正在运行的客户端发送消息。我用方法在Interface-DLL中引入了IClient-Interfacevoid ReceiveMessage(string message);

MainWindow.xaml.cs 正在实现 IClient 接口。

我现在的问题是,当我只有 Process-Object 时,如何在我的服务器中获取 IClient-Object。我想过Activator.CreateInstance,但我不知道如何做到这一点。我很确定我可以通过进程的句柄获得 IClient,但我不知道如何。

任何想法?

4

3 回答 3

4

正如其他帖子提到的一种常见方法是创建服务,也让它更简单,我会考虑看看ServiceStack。AFAIK ServiceStack 用于stackoverflow

也有关于它的课程

ServiceStack 非常容易托管在任何 .net dll 中(没有 iis 等),并且没有 WCF 的配置复杂性。

端点也可作为 SOAP 和 REST 使用,无需配置任何东西

例如,这定义了一个 hello world 服务

public class HelloService : IService<Hello>
{
    public object Execute(Hello request)
    {
        return new HelloResponse { Result = "Hello, " + request.Name };
    }
}

这是客户端代码的示例:

var response = client.Send<HelloResponse>(new Hello { Name = "World!" });
Console.WriteLine(response.Result); // => Hello, World

您可以在以下位置找到更复杂的示例和演练:ServiceStack.Hello

于 2013-07-15T06:21:41.030 回答
1

多进程之间的通信有多种实现方式。像socket、fileMapping、共享内存、windows 32消息等等。

也许示例方式是您可以使用 WCF。

于 2013-07-15T06:03:18.813 回答
0

有很多方法可以进行进程间通信,
但如果您正在寻找一种快速简便的解决方案,您可能需要查看 ZeroMQ。
WCF 也是一种选择,但在您的情况下它可能是矫枉过正。

您可以在此处找到有关 ZeroMQ 的更多信息:http ://www.zeromq.org/ 您可以使用 NuGet 将其安装到您的项目中。

一个带有 aserver和 a的简单示例client

服务器侦听连接,需要一个字符串,反转该字符串并返回它:

public class Server
{
    public Server()
    {

    }

    public void Listen()
    {
        Task.Run(() =>
        {
            using (var context = new Context())
            {
                //Open a socket to reply
                using (var socket = context.Socket(SocketType.REP))
                {
                    socket.Bind("tcp://127.0.0.1:32500");
                    while (true)
                    {
                        //Again you could also receive binary data if you want
                        var request = socket.Recv(Encoding.UTF8);
                        var response = ReverseString(request);
                        socket.Send(response, Encoding.UTF8);
                    }
                }
            }
        });
    }

    private string ReverseString(string request)
    {
        var chars = request.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }
}

客户端连接到服务器(在这种情况下是同一台机器):

public class Client
{
    public Client()
    {

    }

    public string ReverseString(string message)
    {
        using (var context = new Context())
        {
            //Open a socket to request data
            using (var socket = context.Socket(SocketType.REQ))
            {
                socket.Connect("tcp://127.0.0.1:32500");

                //Send a string, you can send a byte[] as well, for example protobuf encoded data
                socket.Send(message, Encoding.UTF8);

                //Get the response from the server
                return socket.Recv(Encoding.UTF8);
            }
        }
    }
}

为了测试它,程序可能如下所示:

public class Program
{
    public static void Main()
    {
        new Program();
    }

    public Program()
    {
        var server = new Server();
        server.Listen();

        var client = new Client();

        var input = String.Empty;

        while (input != "/quit")
        {
            input = Console.ReadLine();
            Console.WriteLine(client.ReverseString(input));
        }
    }

}

这很容易,它可以完成工作。

另一种选择是为 IPC 使用命名管道:http: //www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes

于 2013-07-15T06:11:33.190 回答