Netty TCP Binding decoding with +27 bytes to a C++ Server
jdmarti1_rc Aug 27, 2015 5:25 PMHowdy!
Have a reference service of type Netty TCP defined as
<netty:binding.tcp name="TS1_FacadeProxy_Outbound">
<netty:contextMapper includes=".*"/>
<netty:messageComposer class="mil.navy.e6b.wst.facade.trainerCommon.data.composer.TrainerComposer"/>
<netty:host>wst-master-ios-1</netty:host>
<netty:port>23743</netty:port>
<netty:allowDefaultCodec>true</netty:allowDefaultCodec>
<netty:sync>false</netty:sync>
In the Composer class decompose method I have as follows which
Object content = exchange.getMessage().getContent();
if (content instanceof TrainerCommon) {
exchange.getMessage().setContent(
((TrainerCommon) content).decompose());
}
target = super.decompose(exchange, target);
return super.decompose(exchange, target);
The decompose of the class implementation is simply creating a byte[] of a known size
public byte[] decompose() {
// WST Header = 4 + int dword = 8
ByteBuffer aByteBuffer = ByteBuffer.allocate(8);
getWSTHeader().setByteCount(aByteBuffer.array().length);
try {
DataUtils.getTrainerWSTHeader(this.getWSTHeader(), aByteBuffer);
aByteBuffer.put(DataUtils.getTrainerInt(this.getTrainingSetID(), WinIntType.DWORD));
} catch (DecoderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return aByteBuffer.array();
}
Which yields:
byte[8] = { 4, -111, 8, 0, 1, 0, 0, 0 };
When using from within Switchyard as defined above, the 8 byte send to the C++ Server allows yields 37 bytes. If I use a Client using what I "think" are the same classes as the Switchyard implementation would be using, there are NO issues at all
Standalone client 'snip'... FYI: tried to change the bootstrap.setOption and none of the changes I introduce changes the behavior... this standlone client always runs.
...
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
....
public static void main(String[] args) {
new FacadeProxyClient().connect("wst-facade", port);
}
public void connect(String host, int port) {
ChannelFactory factory = new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
bootstrap = new ClientBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new TcpClientHandler());
}
});
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
// netty:allowDefaultCodec false
bootstrap.setOption("allowDefaultCodec", false);
// netty:sync false
bootstrap.setOption("sync", false);
// netty:sendBufferSize
//bootstrap.setOption("sendBufferSize", 48000);
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host,
port));
Channel channel = future.awaitUninterruptibly().getChannel();
byte[] aFacadeRequest = { 3, -111, 20, 0, 49, 50, 55, 46, 48, 46, 48,
46, 49, 0, 0, 0, 0, 0, 0, 0 };
byte[] aFacadeResponse = { 4, -111, 8, 0, 1, 0, 0, 0 };
// *******************************************************************************
// TODO: Set your bytestream here to send
byte[] messageToSend = aFacadeResponse ;
for (int x=0; x < 1; x++) {
ChannelBuffer buffer = ChannelBuffers
.wrappedBuffer(messageToSend);
ChannelFuture aChannelFuture = channel.write(buffer);
System.out.println("Done? " + aChannelFuture.isDone());
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Was able to modify camel-netty-binding sample with a reference service and cause the same behavior.
Have tried some other netty parameters, such as transferExchange false and it caused a consistent 1673 bytes for an 8 byte decompose.
Tried using a @Produces @Named("mydecoder") with different ChannelHandlerFactories, and either caused complete failure in the client or "nothing would happen at all" behaviors.
Any ideas at all?? Wireshark shows the following:
[eth header][ip header][protocol header][?+27][data]
Traced the code and data to this:
org.jboss.netty.handler.codec.serialization.ObjectEncoder
The returned encoded object contains:
[0, 0, 0, 33, 5, 117, 114, 0, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, 112, 0, 0, 0, 8, 4, -111, 8, 0, 1, 0, 0, 0, 0, 0,....]
The data intended for the c++ server starts at 30 and is: 4, -111, 8, 0, 1, 0, 0, 0
To suppress this for the receiving side, am I going to have to create a custom decoder which calls a custom instance of OneToOneEncoder? Any other approach with parameters??
Added the c++ server and java client that sends correctly...
-
FacadeProxyClient.zip 77.8 KB