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