无法通过命名管道发送 protobuf 流并取回结果

Failing to send protobuf stream over a named pipe and getting result back

我在使用命名管道来回发送对象(双工通信)时遇到问题。代码:

Dto:

[ProtoContract]
public class ServerResponse
{
    [ProtoMember(1)]
    public string FirstName { get; set; }

    [ProtoMember(2)]
    public string LastName { get; set; }
}

[ProtoContract]
public class ServerRequest
{
    [ProtoMember(1)]
    public string Name { get; set; }

    [ProtoMember(2)]
    public int Age { get; set; }
}

服务器:

static void Main(string[] args)
{
    Console.WriteLine("Starting Server");
    StartServer();
    Console.WriteLine("Press any key to stop server..");
    Console.ReadKey();
}

static void StartServer()
{
    Task.Factory.StartNew(() =>
    {
        var server = new NamedPipeServerStream("MyPipes");

        server.WaitForConnection();
        Console.WriteLine("Connected");

        //StreamReader reader = new StreamReader(server);
        //StreamWriter writer = new StreamWriter(server);
        while (true)
        {
            //string line = reader.ReadLine();
            //Console.WriteLine(line);
            //writer.WriteLine(line.ToUpper());
            //writer.Flush();

            var request = Serializer.Deserialize<ServerRequest>(server);
            Console.WriteLine($"Name: {request.Name}, Age: {request.Age}");

            var response = new ServerResponse() { FirstName = request.Name, LastName = "Always this name!" };
            Serializer.Serialize(server, response);
            server.Flush();
        }
    });
}

客户:

static void Main(string[] args)
{
    Console.WriteLine("Client");

    var client = new NamedPipeClientStream("MyPipes");
    client.Connect();

    //StreamReader reader = new StreamReader(client);
    //StreamWriter writer = new StreamWriter(client);
    while (true)
    {
        //string input = Console.ReadLine();
        //if (String.IsNullOrEmpty(input)) break;
        //writer.WriteLine(input);
        //writer.Flush();
        //Console.WriteLine(reader.ReadLine());

        string firstName = Console.ReadLine();
        var request = new ServerRequest() { Name = firstName, Age = firstName.Length };
        Serializer.Serialize(client, request);
        client.Flush();

        var response = Serializer.Deserialize<ServerResponse>(client);
        Console.WriteLine($"Name: {response.FirstName}, Age: {response.LastName}");
    }

    Console.WriteLine("Done");
    Console.ReadKey();
}

发送单行 string 时工作正常,但 protobuf 对我失败。

出于某种原因,Deserialize 方法似乎永远不会停止从流中读取数据,因此我永远无法解码编码服务器请求。但是如果客户端被强行停止,那么请求就会被接收到。

我也试过使用SteamWriterStreamReader都没有用..是否可以在双工通信中传输protobuf对象?如果有人指出我做错了什么,我将不胜感激..

protobuf 不是一种自终止数据格式;你需要使用某种框架。幸运的是,为方便起见,该库包含一些基本实现,因此:如果您使用 SerializeWithLengthPrefixDeserializeWithLengthPrefix(确保两边使用相同的配置):它应该可以工作。

没有框架:protobuf 的本质是 "read until the end of the stream",即您所看到的。这样做的原因是 protobuf 被设计为可连接的(这是一个词吗?)即使对于单个消息