1

我正在使用服务器流式处理应用程序。

问题是客户端没有从服务器流中读取数据。

这是我的proto服务:

service UserService {
    rpc GetData(Id) returns (stream DataResponse) {}
}
message Id {
    int32 id = 1;
}

message DataResponse {
    bytes data = 1;
}

c#服务器是这样的:

public override async Task GetData(Id request, IServerStreamWriter<DataResponse> response, ServerCallContext context)
{
    var user = {} // get user
    foreach (var d in user.Data)
    {
        await response.WriteAsync(new DataResponse { Data = d });
    }
}

它之所以有效,是因为我有一个 NodeJS 客户端,我可以在其中调用服务器并完美运行。

Node中的客户端是

let call = client.getData({id:1})
call.on('data', function (response) {
    // do things
})
call.on('end', function () {
    // do things
})

而c#客户端是:

AsyncServerStreamingCall<DataResponse> response = client.GetData(new Id{Id_ = 1});
while(await response.ResponseStream.MoveNext())
{
    Console.WriteLine("Into while loop"); // <-- This is never executed
    DataResponse current = response.ResponseStream.Current;
    Console.WriteLine($"{current.Data}");
}

我还添加了 atry/catch并且它不输出任何东西,所以它似乎MoveNext()总是false.

这里有什么问题?为什么 NodeJS 客户端可以工作而 c# 客户端无法读取流?我错过了什么吗?

这是完整的 client.cs 类:

class Program
{
    const int Port = 50051;
    static void Main(string[] args)
    {
        try
        {
            Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
            var client = new UserService.UserServiceClient(channel);
            GetDataStreaming(client);
        }
        catch (RpcException ex)
        {
            Console.WriteLine($"Error: {{Code: {ex.StatusCode}, Status: {ex.Status.Detail}}}");
        }
    }

    private static async void GetDataStreaming(UserService.UserServiceClient client)
    {
        
            AsyncServerStreamingCall<DataResponse> response = client.GetData(new Id { Id_ = 1 });
            while (await response.ResponseStream.MoveNext())
            {
                Console.WriteLine("Into while loop");
                DataResponse current = response.ResponseStream.Current;
                Console.WriteLine($"{current.Data.ToStringUtf8()}");
            }

    }

}
4

1 回答 1

1

问题是您的客户端在客户端收到响应之前已经结束。当你打电话GetDataStreaming(client)时,Main它不会等待并完成。

要解决此问题,请更改async void GetDataStreamingasync Task GetDataStreaming.

private static async Task GetDataStreaming(UserService.UserServiceClient client)
{        
        AsyncServerStreamingCall<DataResponse> response = client.GetData(new Id { Id_ = 1 });
        while (await response.ResponseStream.MoveNext())
        {
            Console.WriteLine("Into while loop");
            DataResponse current = response.ResponseStream.Current;
            Console.WriteLine($"{current.Data.ToStringUtf8()}");
        }
}

更改static void Mainstatic async Task Main,您还应该在最后调用channel.ShutdownAsync方法。

static async Task Main(string[] args)
{
    try
    {
        Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
        var client = new UserService.UserServiceClient(channel);
        await GetDataStreaming(client);
        await channel.ShutdownAsync();
    }
    catch (RpcException ex)
    {
        Console.WriteLine($"Error: {{Code: {ex.StatusCode}, Status: {ex.Status.Detail}}}");
    }
}

另一种选择是更改async void GetDataStreamingasync Task GetDataStreaming并在Main方法中等待直到Task完成。

static void Main(string[] args)
{
    try
    {
        Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
        var client = new UserService.UserServiceClient(channel);
        var task = GetDataStreaming(client);
        task.Wait();
    }
    catch (RpcException ex)
    {
        Console.WriteLine($"Error: {{Code: {ex.StatusCode}, Status: {ex.Status.Detail}}}");
    }
}
于 2021-11-03T12:51:46.857 回答