我尝试用gRPC做一个BlackJack游戏来练习,但是我不理解这种流传输。
任务(服务器):
public async Task Deal(Amount dealAmount, IServerStreamWriter<Card> responseStream, ServerCallContext context)
{
this.dealAmount = int.Parse(dealAmount.ToString());
if (deck.Count < 17)
{
deck.Clear();
DeckRead();
Shuffle();
}
FirstDeal();
Card temp = new Card();
temp.Card_ = player[0];
await responseStream.WriteAsync(temp);
temp.Card_ = player[1];
await responseStream.WriteAsync(temp);
temp.Card_ = dealer[0];
await responseStream.WriteAsync(temp);
}
客户:
private async void btDeal_Click(object sender, EventArgs e)
{
Amount dAmount = new Amount();
dAmount.Amount_ = Convert.ToInt32(udDeal.Value);
string newCard;
using (var call = client.Deal(dAmount))
{
var responseStream = call.ResponseStream;
int y = 0;
while (await responseStream.MoveNext())
{
newCard = responseStream.Current.ToString();
if(y == 3)
{
dealer.Add(newCard);
}
else
{
player.Add(newCard);
y++;
}
}
}
dealerCards[0].Load(string.Format("Images/cards/{0}.png", dealer[0]));
dealerCards[1].Load(string.Format("Images/cards/Back/gray_back.png"));
playerCards[0].Load(string.Format("Images/cards/{0}.png", player[0]));
playerCards[1].Load(string.Format("Images/cards/{0}.png", player[1]));
lblDealerAmount.Text = int.Parse(dealer[0].Substring(0, 2)).ToString();
lblPlayerAmount.Text = PlayerAmount().ToString();
money = money - dealAmount;
lblAmount.Text = money.ToString();
btDeal.Enabled = false;
}
proto:
rpc Deal(Amount) returns (stream Card) {}
message Card {
string card=1;
}
message Amount {
int32 amount=1;
}
我知道这不是有史以来最干净的代码,但是现在我只想了解gRCP的工作方式。因此,此任务将前四张卡发给玩家,两张发给玩家,两张发给发牌人,但其中一张发牌者背对后方,因此客户将获得三张卡(他的卡中有2张,发牌人的卡是1张参见)。
首先,由于输入参数,我在 while(await responseStream.MoveNext())处出现异常,但不知道出了什么问题。
RpcException:
mscorlib.dll中发生了'Grpc.Core.RpcException'类型的异常,但未在用户代码中处理 附加信息:Status(StatusCode = Unknown,Detail =“处理程序引发了异常。”)
在服务器的控制台中:
E02/01/2019 13:46:47 Grpc.Core.Internal.ServerStreamingServerCallHandler`2 Exception occured in handler. System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Int32.Parse(String s)
at BlackJackServer.BJS.<Deal>d__14.MoveNext() in C:\Users\tesa3\Desktop\GRPC BEAD\grpc\grpc-master\examples\csharp\BlackJack\BlackJackServer\Program.cs:line 108
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Grpc.Core.Internal.ServerStreamingServerCallHandler`2.<HandleCall>d__0.MoveNext()
另一方面,我不知道在这种情况下我是否正确使用了 WriteAsync 。我的意思是我完全知道客户端会得到三个字符串。我可以先阅读当前内容,然后再阅读 MoveNext 并再次阅读等等吗?
答案 0 :(得分:1)
这看起来像是代码中的问题,与gRPC几乎没有关系。
从错误消息中可以明显看出,它正在服务器端处理程序内发生。让我们在那里看看。
第一行是int.Parse(dealAmount.ToString());
,“ dealAmount”是协议缓冲区消息,ToString()给出了其JSON表示形式(例如,类似{ "Value": 123 }
之类的东西)。显然,这不是int.Parse可以接受的格式(因此出现异常“ System.FormatException:输入字符串的格式不正确。”)。
将protobuf消息转换为字符串然后尝试解析没有任何意义-生成的“金额”类已经使您可以使用正确的类型访问所需的所有字段。