Reputation: 1181
I would like to use netty to create a udp server that reply back.
The old code was in c and used this kind of code :
sockHndl = socket(AF_INET,SOCK_DGRAM,0);
sockConf.sin_family = AF_INET;
sockConf.sin_addr.s_addr = INADDR_ANY;
sockConf.sin_port = htons(33333);
bind(sockHndl, (struct sockaddr*)&sockConf, sizeof(sockConf));
// in a thread
recvfrom(sockHndl, buffer, 1515, 0, (struct sockaddr*)&sockConf, &s);
// process any recevied data
....
// reply
sendto(sockHndl, buffer, strlen(buffer), 0, (struct sockaddr*)&sockConf, sizeof(sockConf));
This code works, but I have to re-implement it in java using netty.
Using netty in tcp is not a problem, but replying with netty to the client is a problem for me, if I want to write on the channel, it failed with a java.nio.channels.NotYetConnectedException
.
Maybe this is linked to this issue on netty, but I don't know how I can reproduce the c behaviour in my code.
final Bootstrap b = new Bootstrap();
b.group(comIOEventLoop).channel(NioDatagramChannel.class).handler(new ChannelInitializer<NioDatagramChannel>()
{
protected void initChannel(NioDatagramChannel ch) throws Exception
{
final ChannelPipeline p = ch.pipeline();
p.addLast("SITCDecoder", new SITCDecoder());
p.addLast("SITCEncoder", new SITCEncoder());
p.addLast("SITCHandler", new SimpleChannelInboundHandler<ITCUdpRequest>()
{
protected void channelRead0(ChannelHandlerContext ctx, ITCUdpRequest msg) throws Exception
{
// here ctx.channel().remoteAddress() == null !
switch(msg.getType())
{
case GET_PARAMS_0:
send(ctx.channel(), new ITCUdpResponse(-80, -20));
break;
}
}
public void send(final Channel channel, final ITCUdpResponse data)
{
if(data == null)
{
LOGGER.error("data == null !!!");
}
channel.writeAndFlush(data).addListener(new GenericFutureListener<Future<Void>>()
{
public void operationComplete(final Future<Void> future) throws Exception
{
if(future.isDone() && future.isSuccess())
{
LOGGER.debug("OK");
}
else
{
LOGGER.error("error " + future.isDone() + " - " + future.isSuccess());
if(!future.isSuccess())
{
future.cause().printStackTrace();
}
}
}
});
}
});
}
});
channel = b.bind(port).sync().channel();
channel.closeFuture().await();
How can I reply to the client ?
Thanks.
Extra edit :
Decoder code :
public class SITCDecoder extends SimpleChannelInboundHandler<DatagramPacket>
{
private static final Logger LOGGER = LoggerFactory.getLogger(SITCDecoder.class);
private static final String MSG_DD_HEADER = "SITCDDVAL:";
private static final int MSG_DD_HEADER_SIZE = MSG_DD_HEADER.length();
protected void channelRead0(final ChannelHandlerContext ctx, final DatagramPacket msg) throws Exception
{
final ByteBuf data = (ByteBuf) msg.content();
if(data != null)
{
// we must be able to read at last <code>MSG_HEADER_SIZE</code> Bytes
if(data.readableBytes() < MSG_DD_HEADER_SIZE)
{
LOGGER.error("Not enought data");
return;
}
if(!data.readBytes(MSG_DD_HEADER_SIZE).toString(StandardCharsets.ISO_8859_1).equals(MSG_DD_HEADER))
{
LOGGER.error("Header not found");
}
final String payload = data.readBytes(data.readableBytes()).toString(StandardCharsets.ISO_8859_1);
final RecyclableArrayList out = RecyclableArrayList.newInstance();
out.add(new ITCUdpRequest(payload));
final int size = out.size();
for(int i = 0; i < size; i++)
{
ctx.fireChannelRead(out.get(i));
}
out.recycle();
}
else
{
ctx.fireChannelRead(msg);
}
}
}
Encoder code :
public class SITCEncoder extends MessageToByteEncoder<ITCUdpResponse>
{
private static final String MSG_RP_HEADER = "SITCRPVAL:";
private static final char MSG_RP_FOOTER = '*';
private static final char VAL_PREFIX = '[';
private static final char VAL_SUFFIX = ']';
protected void encode(final ChannelHandlerContext ctx, final ITCUdpResponse msg, final ByteBuf out) throws Exception
{
final StringBuilder str = new StringBuilder();
str.append(MSG_RP_HEADER);
for(final Object val : msg.getParams())
{
str.append(VAL_PREFIX).append(val).append(VAL_SUFFIX);
}
str.append(MSG_RP_FOOTER);
out.ensureWritable(str.length());
out.writeBytes(str.toString().getBytes());
}
}
Upvotes: 0
Views: 1188