problems on service multi-clients with length field based frames

XuQing Tan missedone at gmail.com
Wed Jan 27 09:01:14 EST 2010


Hi, trustin

thanks for your reply, which bright me up

finally i found there are two problems in my code:
1. the first, i use the default pipeline, as you pointed
2. second, you know that i use spring to inject a list of handler instance
into the server instance, once the server instance is created, the handlers
instance are created too, and in my pipeline factory, i "reuse" the same
handler instance, which cause the same pb as using default pipeline

some suggestion:
1. at the first time when i saw @ChannelPipelineCoverage("one"), i really
confused. after reading some netty source code, i find that this annotation
is used to indicate the handler is some kind "singleton" or not, i mean, if
a handler is annotated with @ChannelPipelineCoverage("one"), the handler is
intended to be created new instance every time in the getPipeline() of the
Pipeline factory, right?
i also remember that you talked about this annotation in some previous
mails, personally, i think, add some "singleton" key word into annotation
name may be much easier to understand

2. after i read some netty source code, that i found the
pipelinefactory.getPipeline() will be called again and again once new
connection/session is created, but i did not find and clue in the
document/javadoc? so if there's some place mention the pipeline factory
life-cycle could help?

anyway, netty is still a agile framework help us developing simple tcp
application in seconds.


 Thanks & Best Regards!

              ///
             (. .)
 --------ooO--(_)--Ooo--------
 |         Nick Tan          |
 -----------------------------



On Tue, Jan 26, 2010 at 7:38 AM, "Trustin Lee (이희승)" <trustin at gmail.com>wrote:

> Hi XuQing,
>
> You have to use Bootstrap.setPipelineFactory() instead of
> Bootstrap.getPipeline() because a LengthFieldBasedFrameDecoder can
> handle only one channel.
>
> Actually, it's always recommended to use Bootstrap.setPipelineFactory().
>  Previous examples were somewhat misleading.  To see it in action, take
> a look into the Factorial example:
>
>
>
> http://www.jboss.org/file-access/default/members/netty/freezone/xref/3.2/org/jboss/netty/example/factorial/FactorialClient.html
>
> All other examples and Javadoc have been updated to reduce user
> confusion and will be deployed at next release (3.2.0.ALPHA4).
>
> HTH,
> Trustin
>
> XuQing Tan wrote:
> > Hi, trustin
> >
> > I recently write a dummy server which parse length field based frames,
> and
> > it works fine only on single client and single request,
> > it failed while i have clients below:
> > 1. if it's single thread, in which there's a "for" loop send several
> request
> > to server
> > 2. if it's multi-thread, in which send several request to server
> > the server side, or more precisely, the corresponding sessions are
> blocked
> > for ever and the EchoHandler never invoked
> >
> > it both occurred on 3.1.5.GA and 3.2.0 trunk
> >
> > the server side code looks like:
> >
> > {code}
> >         ChannelFactory factory = new
> > NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors
> >                 .newCachedThreadPool());
> >
> >         ServerBootstrap bootstrap = new ServerBootstrap(factory);
> >         ChannelPipeline pipeline = bootstrap.getPipeline();
> >
> >         pipeline.addLast("codec", new
> > org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder());
> >         pipeline.addLast("handler", new EchoHandler());
> > {code}
> >
> > it's really simple
> >
> > the client side code are straightforward, it sends length field based
> frame
> > (the length field indicate the full frame length include the length of
> > length), and receive the response data, which is same as the request
> data.
> >
> > could you kindly have a look?
> >
> >
> > * single thread with multi-request client *
> > {code}
> > public class SingleThreadClient {
> >
> >     public static void main(String[] args) throws Exception {
> >         for (int i = 0; i < 100; i++) {
> >             byte[] dataBuf = new byte[1850 + i];
> >             Arrays.fill(dataBuf, (byte) i);
> >
> >             Socket client = new Socket("localhost", 4040);
> >             DataOutputStream req = new
> > DataOutputStream(client.getOutputStream());
> >             DataInputStream resp = new
> > DataInputStream(client.getInputStream());
> >             int datalen = dataBuf.length + 4;
> >             req.writeInt(datalen);
> >
> >             int offset = 0;
> >             int left = dataBuf.length;
> >             while (left > 0) {
> >                 int length = Math.min(1024, left);    // split it into
> multi
> > small fragments
> >                 req.write(dataBuf, offset, length);
> >                 offset += length;
> >                 left -= length;
> >             }
> >             req.flush();
> >
> >             int len = resp.readInt();
> >             byte[] byResp = new byte[len - 4];
> >             resp.read(byResp);
> >             System.out.println(i + " resp data len: " + byResp.length);
> >
> >             client.close();
> >         }
> >     }
> >
> > }
> > {code}
> >
> >
> > * multi thread client *
> > {code}
> > public class MultiThreadClient {
> >
> >     public static void main(String[] args) throws Exception {
> >         ExecutorService exec = Executors.newFixedThreadPool(20);
> >         for (int i = 0; i < 100; i++) {
> >             exec.execute(new SocketTestClient(i));
> >         }
> >     }
> >
> >     private static class SocketTestClient implements Runnable {
> >
> >         private int initVal;
> >
> >         public SocketTestClient(int initVal) {
> >             this.initVal = initVal;
> >         }
> >
> >         public void run() {
> >             try {
> >                 byte[] dataBuf = new byte[1850 + initVal];
> >                 Arrays.fill(dataBuf, (byte) initVal);
> >
> >                 Socket client = new Socket("localhost", 4040);
> >                 DataOutputStream req = new
> > DataOutputStream(client.getOutputStream());
> >                 DataInputStream resp = new
> > DataInputStream(client.getInputStream());
> >                 int datalen = dataBuf.length + 4;
> >                 req.writeInt(datalen);
> >
> >                 int offset = 0;
> >                 int left = dataBuf.length;
> >                 while (left > 0) {
> >                     int length = Math.min(1024, left);
> >                     req.write(dataBuf, offset, length);
> >                     offset += length;
> >                     left -= length;
> >                 }
> >                 req.flush();
> >
> >                 int len = resp.readInt();
> >                 byte[] byResp = new byte[len - 4];
> >                 resp.read(byResp);
> >                 System.out.println(initVal + " resp data len: " +
> > byResp.length);
> >
> >                 client.close();
> >             } catch (Exception e) {
> >                 e.printStackTrace();
> >             }
> >         }
> >     }
> > }
> > {code}
> >
> >
> >
> >  Thanks & Best Regards!
> >
> >               ///
> >              (. .)
> >  --------ooO--(_)--Ooo--------
> >  |         Nick Tan          |
> >  -----------------------------
> >
> >
> >
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > netty-users mailing list
> > netty-users at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/netty-users
>
> --
> what we call human nature in actuality is human habit
> http://gleamynode.net/
>
>
>
> _______________________________________________
> netty-users mailing list
> netty-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/netty-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/netty-users/attachments/20100127/c356bb24/attachment.html 


More information about the netty-users mailing list