Removed the reference to ChannelPipelineCoverage in the getting started guide. Beginners should simply start from creating a new instance for every new connection, as shown in the guide and all examples which were revised to avoid confusion.
Shared instances are more advanced topic, which will be addressed in another chapter.
This commit is contained in:
parent
901b1f099a
commit
2f7c758fe6
@ -73,15 +73,14 @@
|
|||||||
</para>
|
</para>
|
||||||
<programlisting>package org.jboss.netty.example.discard;
|
<programlisting>package org.jboss.netty.example.discard;
|
||||||
|
|
||||||
@&ChannelPipelineCoverage;("all")<co id="example.discard.co1"/>
|
public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="example.discard.co1"/>
|
||||||
public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="example.discard.co2"/>
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {<co id="example.discard.co3"/>
|
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {<co id="example.discard.co2"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(&ChannelHandlerContext; ctx, &ExceptionEvent; e) {<co id="example.discard.co4"/>
|
public void exceptionCaught(&ChannelHandlerContext; ctx, &ExceptionEvent; e) {<co id="example.discard.co3"/>
|
||||||
e.getCause().printStackTrace();
|
e.getCause().printStackTrace();
|
||||||
|
|
||||||
&Channel; ch = e.getChannel();
|
&Channel; ch = e.getChannel();
|
||||||
@ -90,16 +89,6 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
|||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
<callout arearefs="example.discard.co1">
|
<callout arearefs="example.discard.co1">
|
||||||
<para>
|
|
||||||
&ChannelPipelineCoverage; annotates a handler type to tell if the
|
|
||||||
handler instance of the annotated type can be shared by more than
|
|
||||||
one &Channel; (and its associated &ChannelPipeline;).
|
|
||||||
<classname>DiscardServerHandler</classname> does not manage any
|
|
||||||
stateful information, and therefore it is annotated with the value
|
|
||||||
<literal>"all"</literal>.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="example.discard.co2">
|
|
||||||
<para>
|
<para>
|
||||||
<classname>DiscardServerHandler</classname> extends
|
<classname>DiscardServerHandler</classname> extends
|
||||||
&SimpleChannelHandler;, which is an implementation of
|
&SimpleChannelHandler;, which is an implementation of
|
||||||
@ -109,7 +98,7 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
|||||||
the handler interfaces by yourself.
|
the handler interfaces by yourself.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.discard.co3">
|
<callout arearefs="example.discard.co2">
|
||||||
<para>
|
<para>
|
||||||
We override the <methodname>messageReceived</methodname> event
|
We override the <methodname>messageReceived</methodname> event
|
||||||
handler method here. This method is called with a &MessageEvent;,
|
handler method here. This method is called with a &MessageEvent;,
|
||||||
@ -118,7 +107,7 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
|||||||
nothing to implement the DISCARD protocol.
|
nothing to implement the DISCARD protocol.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.discard.co4">
|
<callout arearefs="example.discard.co3">
|
||||||
<para>
|
<para>
|
||||||
<methodname>exceptionCaught</methodname> event handler method is
|
<methodname>exceptionCaught</methodname> event handler method is
|
||||||
called with an &ExceptionEvent; when an exception was raised by
|
called with an &ExceptionEvent; when an exception was raised by
|
||||||
@ -154,14 +143,14 @@ public class DiscardServer {
|
|||||||
|
|
||||||
bootstrap.setPipelineFactory(new &ChannelPipelineFactory;() {<co id="example.discard2.co3" />
|
bootstrap.setPipelineFactory(new &ChannelPipelineFactory;() {<co id="example.discard2.co3" />
|
||||||
public &ChannelPipeline; getPipeline() {
|
public &ChannelPipeline; getPipeline() {
|
||||||
return &Channels;.pipeline(new DiscardServerHandler());<co id="example.discard2.co4" />
|
return &Channels;.pipeline(new DiscardServerHandler());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap.setOption("child.tcpNoDelay", true);<co id="example.discard2.co5" />
|
bootstrap.setOption("child.tcpNoDelay", true);<co id="example.discard2.co4" />
|
||||||
bootstrap.setOption("child.keepAlive", true);
|
bootstrap.setOption("child.keepAlive", true);
|
||||||
|
|
||||||
bootstrap.bind(new InetSocketAddress(8080));<co id="example.discard2.co6" />
|
bootstrap.bind(new InetSocketAddress(8080));<co id="example.discard2.co5" />
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
@ -200,13 +189,6 @@ public class DiscardServer {
|
|||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.discard2.co4">
|
<callout arearefs="example.discard2.co4">
|
||||||
<para>
|
|
||||||
Strictly speaking, we do not need to create a new
|
|
||||||
<classname>DiscardServerHandler</classname> instance for a new
|
|
||||||
connection because the handler is stateless.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="example.discard2.co5">
|
|
||||||
<para>
|
<para>
|
||||||
You can also set the parameters which are specific to the &Channel;
|
You can also set the parameters which are specific to the &Channel;
|
||||||
implementation. We are writing a TCP/IP server, so we are allowed
|
implementation. We are writing a TCP/IP server, so we are allowed
|
||||||
@ -219,7 +201,7 @@ public class DiscardServer {
|
|||||||
<programlisting>bootstrap.setOption("reuseAddress", true);</programlisting>
|
<programlisting>bootstrap.setOption("reuseAddress", true);</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.discard2.co6">
|
<callout arearefs="example.discard2.co5">
|
||||||
<para>
|
<para>
|
||||||
We are ready to go now. What's left is to bind to the port and to
|
We are ready to go now. What's left is to bind to the port and to
|
||||||
start the server. Here, we bind to the port <literal>8080</literal>
|
start the server. Here, we bind to the port <literal>8080</literal>
|
||||||
@ -260,6 +242,7 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
|||||||
&ChannelBuffer;<co id="example.discard3.co1"/> buf = (ChannelBuffer) e.getMessage();
|
&ChannelBuffer;<co id="example.discard3.co1"/> buf = (ChannelBuffer) e.getMessage();
|
||||||
while(buf.readable()) {
|
while(buf.readable()) {
|
||||||
System.out.println((char) buf.readByte());
|
System.out.println((char) buf.readByte());
|
||||||
|
System.out.flush();
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
@ -353,7 +336,6 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
|||||||
</para>
|
</para>
|
||||||
<programlisting>package org.jboss.netty.example.time;
|
<programlisting>package org.jboss.netty.example.time;
|
||||||
|
|
||||||
@&ChannelPipelineCoverage;("all")
|
|
||||||
public class TimeServerHandler extends &SimpleChannelHandler; {
|
public class TimeServerHandler extends &SimpleChannelHandler; {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -447,7 +429,7 @@ ch.close();</programlisting>
|
|||||||
method after the &ChannelFuture;, which was returned by the
|
method after the &ChannelFuture;, which was returned by the
|
||||||
<methodname>write</methodname> method, notifies you when the write
|
<methodname>write</methodname> method, notifies you when the write
|
||||||
operation has been done. Please note that, <methodname>close</methodname>
|
operation has been done. Please note that, <methodname>close</methodname>
|
||||||
might not close the connection immediately, and it returns a
|
also might not close the connection immediately, and it returns a
|
||||||
&ChannelFuture;.
|
&ChannelFuture;.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
@ -545,7 +527,6 @@ public class TimeClient {
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@&ChannelPipelineCoverage;("all")
|
|
||||||
public class TimeClientHandler extends &SimpleChannelHandler; {
|
public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -633,17 +614,16 @@ import static org.jboss.netty.buffer.&ChannelBuffers;.*;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@&ChannelPipelineCoverage;("one")<co id="example.time3.co1"/>
|
|
||||||
public class TimeClientHandler extends &SimpleChannelHandler; {
|
public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||||
|
|
||||||
private final &ChannelBuffer; buf = dynamicBuffer();<co id="example.time3.co2"/>
|
private final &ChannelBuffer; buf = dynamicBuffer();<co id="example.time3.co1"/>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||||
&ChannelBuffer; m = (&ChannelBuffer;) e.getMessage();
|
&ChannelBuffer; m = (&ChannelBuffer;) e.getMessage();
|
||||||
buf.writeBytes(m);<co id="example.time3.co3"/>
|
buf.writeBytes(m);<co id="example.time3.co2"/>
|
||||||
|
|
||||||
if (buf.readableBytes() >= 4) {<co id="example.time3.co4"/>
|
if (buf.readableBytes() >= 4) {<co id="example.time3.co3"/>
|
||||||
long currentTimeMillis = buf.readInt() * 1000L;
|
long currentTimeMillis = buf.readInt() * 1000L;
|
||||||
System.out.println(new Date(currentTimeMillis));
|
System.out.println(new Date(currentTimeMillis));
|
||||||
e.getChannel().close();
|
e.getChannel().close();
|
||||||
@ -658,30 +638,19 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
|||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
<callout arearefs="example.time3.co1">
|
<callout arearefs="example.time3.co1">
|
||||||
<para>
|
|
||||||
This time, <literal>"one"</literal> was used as the value of the
|
|
||||||
&ChannelPipelineCoverage; annotation. It's because the new
|
|
||||||
<classname>TimeClientHandler</classname> has to maintain the internal
|
|
||||||
buffer and therefore cannot serve multiple &Channel;s. If an
|
|
||||||
instance of <classname>TimeClientHandler</classname> is shared by
|
|
||||||
multiple &Channel;s (and consequently multiple &ChannelPipeline;s),
|
|
||||||
the content of the <varname>buf</varname> will be corrupted.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="example.time3.co2">
|
|
||||||
<para>
|
<para>
|
||||||
A <firstterm>dynamic buffer</firstterm> is a &ChannelBuffer; which
|
A <firstterm>dynamic buffer</firstterm> is a &ChannelBuffer; which
|
||||||
increases its capacity on demand. It's very useful when you don't
|
increases its capacity on demand. It's very useful when you don't
|
||||||
know the length of the message.
|
know the length of the message.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.time3.co3">
|
<callout arearefs="example.time3.co2">
|
||||||
<para>
|
<para>
|
||||||
First, all received data should be cumulated into
|
First, all received data should be cumulated into
|
||||||
<varname>buf</varname>.
|
<varname>buf</varname>.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.time3.co4">
|
<callout arearefs="example.time3.co3">
|
||||||
<para>
|
<para>
|
||||||
And then, the handler must check if <varname>buf</varname> has enough
|
And then, the handler must check if <varname>buf</varname> has enough
|
||||||
data, 4 bytes in this example, and proceed to the actual business
|
data, 4 bytes in this example, and proceed to the actual business
|
||||||
@ -729,35 +698,28 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
|||||||
</para>
|
</para>
|
||||||
<programlisting>package org.jboss.netty.example.time;
|
<programlisting>package org.jboss.netty.example.time;
|
||||||
|
|
||||||
<co id="example.time4.co1"/>
|
|
||||||
public class TimeDecoder extends &FrameDecoder; {
|
public class TimeDecoder extends &FrameDecoder; {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object decode(
|
protected Object decode(
|
||||||
&ChannelHandlerContext; ctx, &Channel; channel, &ChannelBuffer; buffer)<co id="example.time4.co2"/> {
|
&ChannelHandlerContext; ctx, &Channel; channel, &ChannelBuffer; buffer)<co id="example.time4.co1"/> {
|
||||||
|
|
||||||
if (buffer.readableBytes() < 4) {
|
if (buffer.readableBytes() < 4) {
|
||||||
return null; <co id="example.time4.co3"/>
|
return null; <co id="example.time4.co2"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.readBytes(4);<co id="example.time4.co4"/>
|
return buffer.readBytes(4);<co id="example.time4.co3"/>
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
<callout arearefs="example.time4.co1">
|
<callout arearefs="example.time4.co1">
|
||||||
<para>
|
|
||||||
There's no &ChannelPipelineCoverage; annotation this time because
|
|
||||||
&FrameDecoder; is already annotated with <literal>"one"</literal>.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="example.time4.co2">
|
|
||||||
<para>
|
<para>
|
||||||
&FrameDecoder; calls <methodname>decode</methodname> method with
|
&FrameDecoder; calls <methodname>decode</methodname> method with
|
||||||
an internally maintained cumulative buffer whenever new data is
|
an internally maintained cumulative buffer whenever new data is
|
||||||
received.
|
received.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.time4.co3">
|
<callout arearefs="example.time4.co2">
|
||||||
<para>
|
<para>
|
||||||
If <literal>null</literal> is returned, it means there's not
|
If <literal>null</literal> is returned, it means there's not
|
||||||
enough data yet. &FrameDecoder; will call again when there is a
|
enough data yet. &FrameDecoder; will call again when there is a
|
||||||
@ -926,27 +888,19 @@ public void channelConnected(&ChannelHandlerContext; ctx, &ChannelStateEvent; e)
|
|||||||
|
|
||||||
import static org.jboss.netty.buffer.&ChannelBuffers;.*;
|
import static org.jboss.netty.buffer.&ChannelBuffers;.*;
|
||||||
|
|
||||||
@&ChannelPipelineCoverage;("all")<co id="example.time6.co1"/>
|
|
||||||
public class TimeEncoder extends &SimpleChannelHandler; {
|
public class TimeEncoder extends &SimpleChannelHandler; {
|
||||||
|
|
||||||
public void writeRequested(&ChannelHandlerContext; ctx, &MessageEvent;<co id="example.time6.co2"/> e) {
|
public void writeRequested(&ChannelHandlerContext; ctx, &MessageEvent;<co id="example.time6.co1"/> e) {
|
||||||
UnixTime time = (UnixTime) e.getMessage();
|
UnixTime time = (UnixTime) e.getMessage();
|
||||||
|
|
||||||
&ChannelBuffer; buf = buffer(4);
|
&ChannelBuffer; buf = buffer(4);
|
||||||
buf.writeInt(time.getValue());
|
buf.writeInt(time.getValue());
|
||||||
|
|
||||||
&Channels;.write(ctx, e.getFuture(), buf);<co id="example.time6.co3"/>
|
&Channels;.write(ctx, e.getFuture(), buf);<co id="example.time6.co2"/>
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
<calloutlist>
|
<calloutlist>
|
||||||
<callout arearefs="example.time6.co1">
|
<callout arearefs="example.time6.co1">
|
||||||
<para>
|
|
||||||
The &ChannelPipelineCoverage; value of an encoder is usually
|
|
||||||
<literal>"all"</literal> because this encoder is stateless.
|
|
||||||
Actually, most encoders are stateless.
|
|
||||||
</para>
|
|
||||||
</callout>
|
|
||||||
<callout arearefs="example.time6.co2">
|
|
||||||
<para>
|
<para>
|
||||||
An encoder overrides the <methodname>writeRequested</methodname>
|
An encoder overrides the <methodname>writeRequested</methodname>
|
||||||
method to intercept a write request. Please note that the
|
method to intercept a write request. Please note that the
|
||||||
@ -962,7 +916,7 @@ public class TimeEncoder extends &SimpleChannelHandler; {
|
|||||||
between a upstream event and a downstream event.
|
between a upstream event and a downstream event.
|
||||||
</para>
|
</para>
|
||||||
</callout>
|
</callout>
|
||||||
<callout arearefs="example.time6.co3">
|
<callout arearefs="example.time6.co2">
|
||||||
<para>
|
<para>
|
||||||
Once done with transforming a POJO into a &ChannelBuffer;, you should
|
Once done with transforming a POJO into a &ChannelBuffer;, you should
|
||||||
forward the new buffer to the previous &ChannelDownstreamHandler; in
|
forward the new buffer to the previous &ChannelDownstreamHandler; in
|
||||||
|
Loading…
Reference in New Issue
Block a user