Hi, trustin<br><br>thanks for your reply, which bright me up<br><br>finally i found there are two problems in my code:<br>1. the first, i use the default pipeline, as you pointed<br>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 <br>
<br>some suggestion:<br>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?<br>
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<br><br>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?<br>
<br>anyway, netty is still a agile framework help us developing simple tcp application in seconds.<br><br><br clear="all"> Thanks & Best Regards!<br><br> ///<br> (. .)<br> --------ooO--(_)--Ooo--------<br>
| Nick Tan |<br> -----------------------------<br><br>
<br><br><div class="gmail_quote">On Tue, Jan 26, 2010 at 7:38 AM, "Trustin Lee (이희승)" <span dir="ltr"><<a href="mailto:trustin@gmail.com">trustin@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Hi XuQing,<br>
<br>
You have to use Bootstrap.setPipelineFactory() instead of<br>
Bootstrap.getPipeline() because a LengthFieldBasedFrameDecoder can<br>
handle only one channel.<br>
<br>
Actually, it's always recommended to use Bootstrap.setPipelineFactory().<br>
Previous examples were somewhat misleading. To see it in action, take<br>
a look into the Factorial example:<br>
<br>
<br>
<a href="http://www.jboss.org/file-access/default/members/netty/freezone/xref/3.2/org/jboss/netty/example/factorial/FactorialClient.html" target="_blank">http://www.jboss.org/file-access/default/members/netty/freezone/xref/3.2/org/jboss/netty/example/factorial/FactorialClient.html</a><br>
<br>
All other examples and Javadoc have been updated to reduce user<br>
confusion and will be deployed at next release (3.2.0.ALPHA4).<br>
<br>
HTH,<br>
<font color="#888888">Trustin<br>
</font><div><div></div><div class="h5"><br>
XuQing Tan wrote:<br>
> Hi, trustin<br>
><br>
> I recently write a dummy server which parse length field based frames, and<br>
> it works fine only on single client and single request,<br>
> it failed while i have clients below:<br>
> 1. if it's single thread, in which there's a "for" loop send several request<br>
> to server<br>
> 2. if it's multi-thread, in which send several request to server<br>
> the server side, or more precisely, the corresponding sessions are blocked<br>
> for ever and the EchoHandler never invoked<br>
><br>
> it both occurred on <a href="http://3.1.5.GA" target="_blank">3.1.5.GA</a> and 3.2.0 trunk<br>
><br>
> the server side code looks like:<br>
><br>
> {code}<br>
> ChannelFactory factory = new<br>
> NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors<br>
> .newCachedThreadPool());<br>
><br>
> ServerBootstrap bootstrap = new ServerBootstrap(factory);<br>
> ChannelPipeline pipeline = bootstrap.getPipeline();<br>
><br>
> pipeline.addLast("codec", new<br>
> org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder());<br>
> pipeline.addLast("handler", new EchoHandler());<br>
> {code}<br>
><br>
> it's really simple<br>
><br>
> the client side code are straightforward, it sends length field based frame<br>
> (the length field indicate the full frame length include the length of<br>
> length), and receive the response data, which is same as the request data.<br>
><br>
> could you kindly have a look?<br>
><br>
><br>
> * single thread with multi-request client *<br>
> {code}<br>
> public class SingleThreadClient {<br>
><br>
> public static void main(String[] args) throws Exception {<br>
> for (int i = 0; i < 100; i++) {<br>
> byte[] dataBuf = new byte[1850 + i];<br>
> Arrays.fill(dataBuf, (byte) i);<br>
><br>
> Socket client = new Socket("localhost", 4040);<br>
> DataOutputStream req = new<br>
> DataOutputStream(client.getOutputStream());<br>
> DataInputStream resp = new<br>
> DataInputStream(client.getInputStream());<br>
> int datalen = dataBuf.length + 4;<br>
> req.writeInt(datalen);<br>
><br>
> int offset = 0;<br>
> int left = dataBuf.length;<br>
> while (left > 0) {<br>
> int length = Math.min(1024, left); // split it into multi<br>
> small fragments<br>
> req.write(dataBuf, offset, length);<br>
> offset += length;<br>
> left -= length;<br>
> }<br>
> req.flush();<br>
><br>
> int len = resp.readInt();<br>
> byte[] byResp = new byte[len - 4];<br>
> resp.read(byResp);<br>
> System.out.println(i + " resp data len: " + byResp.length);<br>
><br>
> client.close();<br>
> }<br>
> }<br>
><br>
> }<br>
> {code}<br>
><br>
><br>
> * multi thread client *<br>
> {code}<br>
> public class MultiThreadClient {<br>
><br>
> public static void main(String[] args) throws Exception {<br>
> ExecutorService exec = Executors.newFixedThreadPool(20);<br>
> for (int i = 0; i < 100; i++) {<br>
> exec.execute(new SocketTestClient(i));<br>
> }<br>
> }<br>
><br>
> private static class SocketTestClient implements Runnable {<br>
><br>
> private int initVal;<br>
><br>
> public SocketTestClient(int initVal) {<br>
> this.initVal = initVal;<br>
> }<br>
><br>
> public void run() {<br>
> try {<br>
> byte[] dataBuf = new byte[1850 + initVal];<br>
> Arrays.fill(dataBuf, (byte) initVal);<br>
><br>
> Socket client = new Socket("localhost", 4040);<br>
> DataOutputStream req = new<br>
> DataOutputStream(client.getOutputStream());<br>
> DataInputStream resp = new<br>
> DataInputStream(client.getInputStream());<br>
> int datalen = dataBuf.length + 4;<br>
> req.writeInt(datalen);<br>
><br>
> int offset = 0;<br>
> int left = dataBuf.length;<br>
> while (left > 0) {<br>
> int length = Math.min(1024, left);<br>
> req.write(dataBuf, offset, length);<br>
> offset += length;<br>
> left -= length;<br>
> }<br>
> req.flush();<br>
><br>
> int len = resp.readInt();<br>
> byte[] byResp = new byte[len - 4];<br>
> resp.read(byResp);<br>
> System.out.println(initVal + " resp data len: " +<br>
> byResp.length);<br>
><br>
> client.close();<br>
> } catch (Exception e) {<br>
> e.printStackTrace();<br>
> }<br>
> }<br>
> }<br>
> }<br>
> {code}<br>
><br>
><br>
><br>
> Thanks & Best Regards!<br>
><br>
> ///<br>
> (. .)<br>
> --------ooO--(_)--Ooo--------<br>
> | Nick Tan |<br>
> -----------------------------<br>
><br>
><br>
><br>
</div></div>> ------------------------------------------------------------------------<br>
<div class="im">><br>
> _______________________________________________<br>
> netty-users mailing list<br>
> <a href="mailto:netty-users@lists.jboss.org">netty-users@lists.jboss.org</a><br>
> <a href="https://lists.jboss.org/mailman/listinfo/netty-users" target="_blank">https://lists.jboss.org/mailman/listinfo/netty-users</a><br>
<br>
</div><div><div></div><div class="h5">--<br>
what we call human nature in actuality is human habit<br>
<a href="http://gleamynode.net/" target="_blank">http://gleamynode.net/</a><br>
<br>
<br>
</div></div><br>_______________________________________________<br>
netty-users mailing list<br>
<a href="mailto:netty-users@lists.jboss.org">netty-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/netty-users" target="_blank">https://lists.jboss.org/mailman/listinfo/netty-users</a><br></blockquote></div><br>