构建Netty的问题

时间:2018-04-02 20:11:48

标签: java netty

框架似乎不起作用......当两个客户端同时连接时,我会从两者中获得相同的数据。

当客户端的通道变为活动状态时,它会发送一个HandshakeRequest,它几乎只是一个包含服务器主机名的字符串,以允许服务器从数据库中获取有关它的一些详细信息。

@Override
public void channelActive(ChannelHandlerContext context) {
    HandshakeRequest packet = new HandshakeRequest();
    packet.setHostname(Client.HOSTNAME);
    context.writeAndFlush(packet);
}

HandshakeRequest:

@Getter @Setter private String hostname;

public HandshakeRequest() {
    super(Packet.HANDSHAKE_REQUEST);
}

@Override
public void write(ByteBuf buf) {
    writeString(hostname, buf);
}

@Override
public void read(ByteBuf buf) {
    hostname = readString(buf);
}

初​​始化器:

@Override
public void initChannel(SocketChannel channel) {
    ChannelPipeline pipeline = channel.pipeline();

    pipeline.addLast(new LengthFieldPrepender(2));
    pipeline.addLast(new PacketEncoder());

    pipeline.addLast(new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, 2, 0, 2));
    pipeline.addLast(new PacketDecoder());

    pipeline.addLast(new ClientHandler(client));
}

PacketEncoder:

@Override
protected void encode(ChannelHandlerContext context, DefinedPacket packet, ByteBuf buf) {
    buf.writeInt(packet.packet().getId());
    packet.write(buf);
}

PacketDecoder:

@Override
protected void decode(ChannelHandlerContext context, ByteBuf in, List<Object> out) {
    int id = in.readInt();
    DefinedPacket packet = Packet.getTypeById(id).getPacket();
    if(packet != null) {
        packet.read(in);
        packet.setId(id);
        out.add(packet);
    } else {
        in.skipBytes(in.readableBytes());
    }
}

DefinedPacket(这是所有数据包扩展的抽象类):

public static void writeString(String s, ByteBuf buf) {
    if(s.length() > Short.MAX_VALUE) {
        throw new OverflowPacketException(String.format("Cannot send string longer than Short.MAX_VALUE (got %s characters)", s.length()));
    }
    byte[] b = s.getBytes(Charsets.UTF_8);
    writeVarInt(b.length, buf);
    buf.writeBytes(b);
}

public static String readString(ByteBuf buf) {
    int len = readVarInt(buf);
    if(len > Short.MAX_VALUE) {
        throw new OverflowPacketException(String.format("Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len));
    }
    byte[] b = new byte[len];
    buf.readBytes(b);
    return new String(b, Charsets.UTF_8);
}

public static int readVarInt(ByteBuf input) {
    return readVarInt(input, 5);
}

public static int readVarInt(ByteBuf input, int maxBytes) {
    int out = 0;
    int bytes = 0;
    byte in;
    while(true) {
        in = input.readByte();
        out |= (in & 0x7F) << (bytes++ * 7);
        if(bytes > maxBytes) {
            throw new RuntimeException("VarInt too big");
        }
        if((in & 0x80) != 0x80) {
            break;
        }
    }
    return out;
}

public static void writeVarInt(int value, ByteBuf output) {
    int part;
    while(true) {
        part = value & 0x7F;
        value >>>= 7;
        if(value != 0) {
            part |= 0x80;
        }
        output.writeByte(part);
        if(value == 0) {
            break;
        }
    }
}

private final Packet type;
@Getter @Setter private int id;

public DefinedPacket(Packet type) {
    this.type = type;
}

public Packet packet() {
    return type;
}

public abstract void write(ByteBuf buf);

public abstract void read(ByteBuf buf);

2 个答案:

答案 0 :(得分:0)

你能为

提供全班吗?
request

...

你将@Override public void initChannel(SocketChannel channel) { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new LengthFieldPrepender(2)); pipeline.addLast(new PacketEncoder()); pipeline.addLast(new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, 2, 0, 2)); pipeline.addLast(new PacketDecoder()); pipeline.addLast(new ClientHandler(client)); } 传递给ClientHandler的构造函数的位置是什么?

答案 1 :(得分:0)

我已经解决了这个问题。事实证明,在解码后处理新的数据包实例的方式是一个问题(为同一个数据包的每个实例重用相同的对象)。这只是一个非常愚蠢的错误:P