[英]Netty server send a byte[] encoded by Protobuf, but C# client Socket.Receive keeps being 0
我正在嘗試使用網絡功能,使用C#進行客戶端編程以及使用Java進行網絡功能來完成Unity游戲演示。 具體而言,服務器通信由Netty實現。 我還引入了Protobuf,它可以幫助我定義消息協議。 由於我是服務器編程的新手,因此我的代碼中尚未考慮處理TCP中的數據包合並和丟失。
當我從客戶端創建套接字並將消息發送到服務器時,一切都進行得很好。 服務器答復時發生了問題:在客戶端中,異步方法已准備就緒,可以接收消息。 當我簡單地從服務器發送字符串格式的消息時,該方法就可以獲取它。 但是,當我用從Protobuf Message對象編碼的4長度byte []替換消息時,客戶端只是表明它收到了NOTHING。
當我打印在服務器控制台中發送的內容時,它是這樣的:00001000 00000001 00010000 00000001
我的服務器代碼覆蓋了Netty的channelRead和channelReadComplete函數。 在channelRead中,調用ChannelHandlerContext.write將消息寫入傳輸緩存。 在channelReadComplete中,調用了ChannelHandlerContext.flush,以便最終可以發送消息。
channelRead()
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Request.MsgPack msgPack = (Request.MsgPack) msg;
Request.MsgPack.MsgType type = msgPack.getType();
switch (type)
{
case GetServerState:
final Request.GetServerState gssbody = msgPack.getGetServerState();
System.out.println("收到類型為" + type + "的消息,內容為:" +
"\nrequestId = " + gssbody.getRequestId()
);
byte[] bytes = ServerStateManager.getState(gssbody.getRequestId());
ctx.write(bytes);
break;
getState():包括Protobuf編碼過程
public static byte[] getState(int requestId)
{
ReturnServerState.Message.Builder replyBuilder = ReturnServerState.Message.newBuilder();
replyBuilder.setRequestId(requestId);
replyBuilder.setIsIdle(new ServerStateManager().isIdle());
return replyBuilder.build().toByteArray();
}
channelReadComplete()
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
try
{
ctx.flush();
}
finally
{
ctx.close();
}
}
客戶代碼:
public class ShortLink
{
Socket clientSocket = null;
static byte[] result = new byte[1024];
Task ReceiveAsync<T>(string ip, int port)
{
return Task.Run(() =>
{
T component = default(T);
while (clientSocket.Receive(result) == 0)
{
break;
通過以下方式調用ReceiveAsync:
await ReceiveAsync<ReturnServerState>(ip, port);
當我發現clientSocket.Receive(result)始終輸出0時,我嘗試記錄result [0],result [1],result [2],result [3],如下所示:
Debug.Log(Convert.ToString(result[0]) + ", " +
Convert.ToString(result[1]) + ", " +
Convert.ToString(result[2]) + ", " +
Convert.ToString(result[3]));
日志變為0,0,0,0。
對於“為什么客戶端套接字什么都沒收到”的任何想法和解決方案,我將不勝感激。 由於我來自亞洲,因此您的答復和我的答復之間可能會有時間間隔,而且英語不是我的母語。 但是,我會盡力及時答復。 非常感謝!
好吧..我終於自己解決了
1.用法“ return replyBuilder.build()。toByteArray()”是錯誤的,因為ProtoEncoder已經為我做過toByteArray():
public class ProtobufEncoder extends MessageToMessageEncoder<MessageLiteOrBuilder> {
public ProtobufEncoder() {
}
protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception {
if (msg instanceof MessageLite) {
out.add(Unpooled.wrappedBuffer(((MessageLite)msg).toByteArray()));
} else {
if (msg instanceof Builder) {
out.add(Unpooled.wrappedBuffer(((Builder)msg).build().toByteArray()));
}
}
}
}
因此,一旦我在Netty Channel Pipeline中注冊了“ new ProtobufEncoder()”,我就可以使用“ return replyBuilder.build()”了-是正確的。
2.在“靜態字節[]結果=新字節[1024];”中,隨意定義接收到的消息的長度,這無關緊要-直到它真正接收到消息為止。
接收消息時,我將始終始終首先將消息字節復制到具有正確長度的新byte []-否則將只有1024個長度的bytes [],開頭是我需要的數據,后面是幾個零,這肯定不會被解碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.