将服务器流式读取到客户端 C#
Read server streaming into client c#
我正在做一个使用服务器流的应用程序。
问题是客户端没有从服务器流中读取数据。
这是我的 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}");
}
我还添加了一个 try/catch
但它没有输出任何内容,所以似乎 MoveNext()
总是 false
.
这里有什么问题?为什么 NodeJS 客户端可以工作而 c# 客户端无法读取流?我错过了什么吗?
此处已满client.csclass:
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()}");
}
}
}
问题是您的客户端在收到响应之前已经结束。当您在 Main
中调用 GetDataStreaming(client)
时,它不会等待并完成。
要解决此问题,请将 async void GetDataStreaming
更改为 async 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 Main
改为static 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 GetDataStreaming
更改为 async 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}}}");
}
}
我正在做一个使用服务器流的应用程序。
问题是客户端没有从服务器流中读取数据。
这是我的 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}");
}
我还添加了一个 try/catch
但它没有输出任何内容,所以似乎 MoveNext()
总是 false
.
这里有什么问题?为什么 NodeJS 客户端可以工作而 c# 客户端无法读取流?我错过了什么吗?
此处已满client.csclass:
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()}");
}
}
}
问题是您的客户端在收到响应之前已经结束。当您在 Main
中调用 GetDataStreaming(client)
时,它不会等待并完成。
要解决此问题,请将 async void GetDataStreaming
更改为 async 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 Main
改为static 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 GetDataStreaming
更改为 async 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}}}");
}
}