簡體   English   中英

Netty服務器發送Protobuf編碼的byte [],但C#客戶端Socket.Receive始終為0

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM