我正在尝试使用自定义协议开发客户端与生物识别设备进行通信,但似乎没有任何效果。 我使用MessageToByteEncoder和MessageToByteDecoder来处理输入和输出数据:
public class PacketDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext context, ByteBuf input, List<Object> out) throws Exception {
System.out.println("readable bytes: " + input.readableBytes());
if (input.readableBytes() >= 1) {
if (input.getByte(0) != DataCodes.START_BYTE) {
input.readByte();
return;
}
}
if (input.readableBytes() >= 3) {
byte command = input.getByte(2);
boolean extendedLenght = (command & 0x80) == 0x80;
short dataLength;
int headerLength;
if (extendedLenght) {
byte[] dataLengthBytes = new byte[2];
input.getBytes(3, dataLengthBytes);
dataLength = Utils.getShort(dataLengthBytes);
headerLength = 5;
} else {
dataLength = input.getByte(3);
headerLength = 4;
}
int totalLength = headerLength + dataLength + 16;
if (input.readableBytes() >= totalLength) {
byte[] packetBytes = input.readBytes(totalLength).array();
Packet packet = PacketConverter.decode(packetBytes);
System.out.println("packet decoded");
out.add(packet);
}
}
}
}
public class PacketEncoder extends MessageToByteEncoder<Packet> {
@Override
protected void encode(ChannelHandlerContext context, Packet packet, ByteBuf out) throws Exception {
byte[] packetBytes = PacketConverter.encode(packet);
out.writeBytes(packetBytes);
}
}
和连接类:
public class Connection implements PacketListener {
private final byte deviceAddress;
private ChannelFuture channelFuture;
private EventLoopGroup workerGroup;
private final Object readLock = new Object();
private Packet responsePacket;
public Connection(byte deviceAddress) {
this.deviceAddress = deviceAddress;
}
public void connect(String address, int port) {
workerGroup = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(
new PacketEncoder(),
new PacketDecoder(),
new PacketHandler(Connection.this)
);
}
});
channelFuture = b.connect(address, port);
}
public void disconnect() {
channelFuture.channel().disconnect().syncUninterruptibly();
workerGroup.shutdownGracefully();
}
@Override
public void receive(Packet packet) {
synchronized (readLock) {
this.responsePacket = packet;
readLock.notify();
}
}
public Response send(Command command, int responseTimeout) throws TimeOutException {
Packet packet = new Packet();
packet.setCommand(command.getCommandCode());
packet.setData(command.getCommandData());
packet.setAddress(deviceAddress);
synchronized (readLock) {
responsePacket = null;
channelFuture.channel().writeAndFlush(packet).syncUninterruptibly();
try {
readLock.wait(responseTimeout);
} catch (InterruptedException e) {
}
if (responsePacket == null)
throw new TimeOutException();
return Response.get(responsePacket);
}
}
}
在解码器上,它带有0个可读字节,我不确定控制器是否正在发送任何数据。我唯一的猜测是服务器需要是一个Netty实现。
答案 0 :(得分:5)
Netty客户端是否仅使用netty服务器?
没有。一般来说,Netty提供网络抽象和事件循环结构,以减轻滚动自己的痛苦和陷阱。
虽然您的示例相对简单,但我建议您根据工作示例构建代码,然后在部分更有意义时添加功能/结构。例如,查看echo examples。尝试使用这种结构,不要担心获得干净的类层次结构(同步,超时等),直到你可以发送/接收一些字节为止。
使用ByteBuf
界面时一般要小心。您的input.getByte(..)
调用使用的绝对索引不是基于readerIndex()
,这可能会导致超出范围的异常。请参阅ByteBuf javadocs,但您可能只想坚持readByte()
或至少使用readerIndex()
。
其他一些常见疑难解答问题:
1)您是否确认您正在发送正确的信息并且设备正在接收它?
2)您是否确认设备正在响应预期的响应?