我正在嘗試在 a 上使用 ProtocolBuffers,NetworkStream但訊息從未完全收到。
這是我的服務器:
var listener = new TcpListener(System.Net.IPAddress.Any, 4989);
listener.Start();
while (true)
{
var client = listener.AcceptTcpClient();
Task.Factory.StartNew(() =>
{
var message = ServerMessage.Parser.ParseFrom(client.GetStream());
Console.WriteLine(message);
});
}
這是我的客戶:
Thread.Sleep(2000);//Wait for server to start
var client = new TcpClient();
client.Connect("localhost", 4989);
while (true)
{
var message = new ServerMessage
{
Time = (ulong)DateTime.UtcNow.Ticks,
Type = MessageType.Content
};
message.WriteTo(client.GetStream());
Thread.Sleep(1000);
}
此處提供完整的重現解決方案:https ://github.com/IanPNewson/ProtobufNetworkStreamIssue
怎么了?
uj5u.com熱心網友回復:
protobuf 不是一個終止的協議,我的意思是:當單個訊息結束時,實際上沒有任何內容。正因為如此,默認情況下:API 像ParseFromread直到流結束,并且在打開的Socket/NetworkStream中:只有當您發送一條訊息然后關閉出站連接時才會發生這種情況(此時沒有更多位元組不是足夠 - 它需要在流上看到一個實際的 EOF,這意味著您只能在每個套接字上發送一條訊息)。
因此,您通常使用帶有 protobuf 的框架,這意味著:在開放流中表示單個訊息的某種方式。這通常通過長度前綴完成(您不能使用標記值終止,因為 protobuf 可以包含任何位元組值)。
一些 API 包括為此提供便利的方法(*WithLengthPrefix例如,protobuf-net 中的 API,盡管您不能將其放在此處)——或者您可以自己手動實作它。或者,也許考慮像 gRPC 這樣的東西,它為你處理所有的框架等語意,這樣你就可以專注于做有趣的作業。如果您真的不想處理 gRPC 的完整 HTTP/2 端,我有一個適用于裸套接字的 gRPC 變體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/468881.html
