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