繁体   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