A few pointers:
1) All objects are instanceof Object, so you can rewrite "else if(message
instance of Object) { ... } " as "else { ... }"
2) You're trying to debug encoding and decoding at the same time, and any
time you see a failure, you don't know which side to fix. Instead write
some unit tests:
- for encoding, encode to a byte[] (via a ByteArrayOutputStream, if you
want your method to use that) and assertEquals against a hand-crafted byte
array
- for decoding, start with a hand-crafted byte array, decode (maybe via
ByteArrayOutputStream and assertEquals against the expected object.
When I say "hand-craft", you can computer-assist the creation. For example,
for one of your samples you can write a short program to just encode an
object, System.out.println(Arrays.toString(byteArray), copy/paste the
result into your unit test code, and add '@' at the front.
Get this all working separately to any networking concerns first. Then work
to address buffer fragmentation.
On Thu Feb 26 2015 at 08:56:06 Emmanuel Lécharny <[email protected]>
wrote:
> Le 26/02/15 08:16, Abeer Al-Anazi a écrit :
> > did you mean like this:
> > encode function:
> > public void encode(IoSession session, Object message,
> > ProtocolEncoderOutput out) throws Exception {
> > byte b;
> > IoBuffer buffer = IoBuffer.allocate(1200, false);
> > buffer.setAutoExpand(true);
> > if (message instanceof Long )
> > { b = '@';
> >
> > buffer.put (b);
> > long controllerCurrentLoad= (Long) message;
> > byte[] bytes3 = getBytes(controllerCurrentLoad);
> > buffer.putInt(bytes3.length);
> > buffer.put(bytes3);
> >
> > }
> > else if ( message instanceof HashMap )
> > { b = '#';
> > HashMap <SocketAddress, Long> loadTable = new
> > HashMap<SocketAddress, Long> ();
> > loadTable = (HashMap<SocketAddress, Long>) message;
> > byte[] bytes1 = getBytes( loadTable);
> > buffer.put(b);
> > buffer.putInt(bytes1.length);
> > buffer.put(bytes1);
> >
> > }
> > else if ( message instanceof Object )
> > {
> > b = '&';
> > buffer.put (b);
> > controllerInfo request = (controllerInfo ) message;
> > byte[] bytes2 = getBytes(request);
> > buffer.putInt(bytes2.length);
> > buffer.put(bytes2);
> > }
> >
> >
> > buffer.flip();
> > out.write(buffer);
> > }
> > *********************************
> > public static byte[] getBytes(Object obj) throws IOException {
> > ByteArrayOutputStream b = new ByteArrayOutputStream();
> > ObjectOutputStream o = new ObjectOutputStream(b);
> > o.writeObject(obj);
> > return b.toByteArray();
> > *****************************************************************
>
>
> The encode function seems ok, IFAICT. I'm not sure that writing a char
> ('@' or '&') will not write 2 bytes instead of 1, which might be a pb
> when decoding, as you may perfectly receive 1 sinle byte first, then the
> remaining bytes. Cast it to a byte.
>
>
> > decode function:
> > rotected boolean doDecode(IoSession session, IoBuffer in,
> > ProtocolDecoderOutput out) throws Exception {
> > byte b = 0 ;
> > long controllerCurrentLoad = 0;
> > controllerInfo r = new controllerInfo();
> > while (in.hasRemaining())
> > {
> > b = in.get();
> >
> > if (b == '&')
> > {
> >
> > if(in.prefixedDataAvailable(4))
>
> You are not dealing with buffer fragmentation here.
>
> What will you do if you don't receive 4 bytes ?
>
>
>
> > {
> > r = (controllerInfo) deserialize(in);
> >
> > }
> > }
> > if (b == '@')
> > {
> > if(in.prefixedDataAvailable(4))
> > {
> > controllerCurrentLoad = (Long) deserialize(in);
> >
> > }
> >
> > }
> > if (b == '#')
> > {
> > if (in.prefixedDataAvailable(4))
> > {
> >
> > HashMap<SocketAddress, Long> l = (HashMap<SocketAddress, Long>)
> > in.getObject();
> > l = (HashMap<SocketAddress, Long>) deserialize(in);
> > loadTable = l;
> > }
> >
> > }
> > }
> > controllerInfo request =r;
> > request.setControllerLoad(controllerCurrentLoad);
> > request.setSwitchesLoad(loadTable);
> > out.write(request);
> > return false;
> > }
> >
> > *********************************************
> > public static Object deserialize(IoBuffer in) throws IOException,
> > ClassNotFoundException {
> > int length = in.getInt();
> > byte[] bytes = new byte[length];
> > in.get(bytes);
> > ByteArrayInputStream b = new ByteArrayInputStream(bytes);
> > ObjectInputStream o = new ObjectInputStream(b);
> > return o.readObject();
> > **********************************************************
> > I tested it but it did not work, and the decoder did not read any things.
> > If I discard using getByte and deserialize function, the decoder read the
> > object only and when I print the renaming in buffer -after read object-
> the
> > result is zero. I mean the decoder read only one of the message cases
> > (object-long-hashmap) and discard others.
>
> Have you printed whet you sent ? Is this what you get on the decoder side ?
>
> Does both buffer contain the initial char, the length and everything
> that you expect to be a serialized object ?
> > I think the problem is in buffer size, because it cant read more than one
>
>
> ???
> > (if cases).
> > I need your help please, I spent a lot of my time to try solving it :(
> Sorry, I do what I can, but at some point, I can't write your
> application...
>
>
>