Reputation: 257
I'm trying to develop a client to communicate with a biometric device using a custom protocol but nothing seems to work. I'm using a MessageToByteEncoder and a MessageToByteDecoder to handle the input and output data:
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);
}
}
and the connnection class:
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);
}
}
}
On the decoder, it aways comes with 0 readableBytes and I not sure the enconder is sending any data at all. My only guess is that the server needs to be a Netty implementation.
Upvotes: 0
Views: 796
Reputation: 746
Does a Netty client work with a netty server only?
No. In general Netty provides networking abstractions and event-loop constructs to alleviate the pains and pitfalls of rolling your own.
Although your example is relatively simple I would recommend structuring your code off of a working example and then add features/structure once the pieces make more sense. For example check out the echo examples. Try using this structure and don't worry about getting a clean class hierarchy (synchronization, timeouts, etc..) until you can send/receive some bytes.
Also in general be careful when you are using the ByteBuf
interface. Your input.getByte(..)
calls are using absolute indexing which is not based on the readerIndex()
which may lead to out of bounds exceptions. Please refer to the ByteBuf javadocs but you may just want to stick with readByte()
or at least use readerIndex()
.
Some other general troubleshooting questions:
1) Have you verified that you are sending correct information and the device is receiving it?
2) Have you verified the device is responding with the anticipated response?
Upvotes: 5