Documentation cleanup
This commit is contained in:
parent
3d83768039
commit
927aaf8d12
@ -22,10 +22,10 @@
|
||||
<title>Before Getting Started</title>
|
||||
<para>
|
||||
The minimum requirements to run the examples which are introduced in
|
||||
this chapter are just two; the latest version of Netty and JDK 1.5 or
|
||||
this chapter are only two; the latest version of Netty and JDK 1.5 or
|
||||
above. The latest version of Netty is available in
|
||||
<ulink url="&Downloads;">the project download page</ulink>. To get the
|
||||
right version of JDK, please refer to your preferred JDK vendor's web
|
||||
<ulink url="&Downloads;">the project download page</ulink>. To download
|
||||
the right version of JDK, please refer to your preferred JDK vendor's web
|
||||
site.
|
||||
</para>
|
||||
<para>
|
||||
@ -53,9 +53,9 @@
|
||||
a protocol which discards any received data without any response.
|
||||
</para>
|
||||
<para>
|
||||
What you are supposed to do to implement the DISCARD protocol is to log
|
||||
the received data, and that's all. Let's start straight from the handler
|
||||
implementation, which handles I/O events generated by Netty.
|
||||
To implement the DISCARD protocol, you only need to log the received data.
|
||||
Let us start straight from the handler implementation, which handles I/O
|
||||
events generated by Netty.
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.discard;
|
||||
|
||||
@ -80,8 +80,8 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
||||
&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> doesn't manage any
|
||||
stateful information, and therefore it's annotated with the value
|
||||
<classname>DiscardServerHandler</classname> does not manage any
|
||||
stateful information, and therefore it is annotated with the value
|
||||
<literal>"all"</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
@ -90,7 +90,7 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
||||
<classname>DiscardServerHandler</classname> extends
|
||||
&SimpleChannelHandler;, which is an implementation of
|
||||
&ChannelHandler;. &SimpleChannelHandler; provides various event
|
||||
handler methods that you can override. For now, it's just enough
|
||||
handler methods that you can override. For now, it is just enough
|
||||
to extend &SimpleChannelHandler; rather than to implement
|
||||
the handler interfaces by yourself.
|
||||
</para>
|
||||
@ -100,8 +100,8 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
||||
We override the <methodname>messageReceived</methodname> event
|
||||
handler method here. This method is called with a &MessageEvent;,
|
||||
which contains the received data, whenever new data is received
|
||||
from a client. In this example, we just ignore the received data
|
||||
by doing nothing to implement the DISCARD protocol.
|
||||
from a client. In this example, we ignore the received data by doing
|
||||
nothing to implement the DISCARD protocol.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.discard.co4">
|
||||
@ -119,9 +119,9 @@ public class DiscardServerHandler extends &SimpleChannelHandler; {<co id="exampl
|
||||
</callout>
|
||||
</calloutlist>
|
||||
<para>
|
||||
So far so good. We have implemented the half of the DISCARD server.
|
||||
So far so good. We have implemented the first half of the DISCARD server.
|
||||
What's left now is to write the <methodname>main</methodname> method
|
||||
which starts the server up with the <classname>DiscardServerHandler</classname>.
|
||||
which starts the server with the <classname>DiscardServerHandler</classname>.
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.discard;
|
||||
|
||||
@ -157,7 +157,7 @@ public class DiscardServer {
|
||||
&ChannelFactory; implementations. We are implementing a server-side
|
||||
application in this example, and therefore
|
||||
&NioServerSocketChannelFactory; was used. Another thing to note is
|
||||
that it doesn't create I/O threads by itself. It is supposed to
|
||||
that it does not create I/O threads by itself. It is supposed to
|
||||
acquire threads from the thread pool you specified in the
|
||||
constructor, and it gives you more control over how threads should
|
||||
be managed in the environment where your application runs, such as
|
||||
@ -167,8 +167,9 @@ public class DiscardServer {
|
||||
<callout arearefs="example.discard2.co2">
|
||||
<para>
|
||||
&ServerBootstrap; is a helper class that sets up a server. You can
|
||||
set up the server by yourself using a &Channel; directly, but it's a
|
||||
tedious process and you won't need to do that in most cases.
|
||||
set up the server using a &Channel; directly. However, please note
|
||||
that this is a tedious process and you do not need to do that in most
|
||||
cases.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.discard2.co3">
|
||||
@ -192,18 +193,18 @@ public class DiscardServer {
|
||||
<literal>keepAlive</literal>. Please note that the
|
||||
<literal>"child."</literal> prefix was added to all options. It
|
||||
means the options will be applied to the accepted &Channel;s instead
|
||||
of the options of the &ServerSocketChannel;. You could do like the following:
|
||||
of the options of the &ServerSocketChannel;. You could do the
|
||||
following to set the options of the &ServerSocketChannel;:
|
||||
<programlisting>bootstrap.setOption("reuseAddress", true);</programlisting>
|
||||
to set the options of the &ServerSocketChannel;.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.discard2.co5">
|
||||
<para>
|
||||
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>
|
||||
of all NICs (network interface cards) in the machine. You are fine
|
||||
to call the <methodname>bind</methodname> method as many times as
|
||||
you want, with different bind addresses.
|
||||
of all NICs (network interface cards) in the machine. You can now
|
||||
call the <methodname>bind</methodname> method as many times as
|
||||
you want (with different bind addresses.)
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
@ -215,21 +216,21 @@ public class DiscardServer {
|
||||
<section>
|
||||
<title>Looking into the Received Data</title>
|
||||
<para>
|
||||
Now that we wrote our first server, we need to test if it really works.
|
||||
The easiest way to test it is to use the <command>telnet</command>
|
||||
Now that we have written our first server, we need to test if it really
|
||||
works. The easiest way to test it is to use the <command>telnet</command>
|
||||
command. For example, you could enter "<command>telnet localhost
|
||||
8080</command>" in the command line and type something.
|
||||
</para>
|
||||
<para>
|
||||
However, can we say that the server is working fine? We can't really
|
||||
know that because it's a discard server. You will not going to get any
|
||||
response at all. To prove it's really working, let's modify the server
|
||||
to print what it has received.
|
||||
However, can we say that the server is working fine? We cannot really
|
||||
know that because it is a discard server. You will not get any response
|
||||
at all. To prove it is really working, let us modify the server to print
|
||||
what it has received.
|
||||
</para>
|
||||
<para>
|
||||
We already know that &MessageEvent; is generated whenever data is
|
||||
received and the <methodname>messageReceived</methodname> handler method
|
||||
will be invoked. Let's put some code into the
|
||||
will be invoked. Let us put some code into the
|
||||
<methodname>messageReceived</methodname> method of the
|
||||
<classname>DiscardServerHandler</classname>:
|
||||
</para>
|
||||
@ -246,7 +247,7 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
It is safe to assume the message type in socket transports is always
|
||||
&ChannelBuffer;. &ChannelBuffer; is a fundamental data structure
|
||||
which stores a sequence of bytes in Netty. It's similar to NIO
|
||||
<classname>ByteBuffer</classname>, but it's easier to use and more
|
||||
<classname>ByteBuffer</classname>, but it is easier to use and more
|
||||
flexible. For example, Netty allows you to create a composite
|
||||
&ChannelBuffer; which combines multiple &ChannelBuffer;s reducing
|
||||
the number of unnecessary memory copy.
|
||||
@ -273,7 +274,7 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
<title>Writing an Echo Server</title>
|
||||
<para>
|
||||
So far, we have been consuming data without responding at all. A server,
|
||||
however, is usually supposed to respond to a request. Let's learn how to
|
||||
however, is usually supposed to respond to a request. Let us learn how to
|
||||
write a response message to a client by implementing the
|
||||
<ulink url="http://tools.ietf.org/html/rfc862">ECHO</ulink> protocol,
|
||||
where any received data is sent back.
|
||||
@ -281,9 +282,8 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
<para>
|
||||
The only difference from the discard server we have implemented in the
|
||||
previous sections is that it sends the received data back instead of
|
||||
printing the received data out to the console. Therefore, it's just
|
||||
enough again to modify the <methodname>messageReceived</methodname>
|
||||
method:
|
||||
printing the received data out to the console. Therefore, it is enough
|
||||
again to modify the <methodname>messageReceived</methodname> method:
|
||||
</para>
|
||||
<programlisting>@Override
|
||||
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
@ -324,10 +324,10 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
</para>
|
||||
<para>
|
||||
Because we are going to ignore any received data but to send a message
|
||||
as soon as a connection is established, we can't use the
|
||||
as soon as a connection is established, we cannot use the
|
||||
<methodname>messageReceived</methodname> method this time. Instead,
|
||||
we should override the <methodname>channelConnected</methodname> method.
|
||||
Here's the implementation:
|
||||
The following is the implementation:
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.time;
|
||||
|
||||
@ -361,7 +361,7 @@ public class TimeServerHandler extends &SimpleChannelHandler; {
|
||||
<callout arearefs="example.time.co1">
|
||||
<para>
|
||||
As explained, <methodname>channelConnected</methodname> method will
|
||||
be invoked when a connection is established. Let's write the 32-bit
|
||||
be invoked when a connection is established. Let us write the 32-bit
|
||||
integer that represents the current time in seconds here.
|
||||
</para>
|
||||
</callout>
|
||||
@ -373,11 +373,11 @@ public class TimeServerHandler extends &SimpleChannelHandler; {
|
||||
<literal>4</literal> bytes. The &ChannelBuffers; helper class is
|
||||
used to allocate a new buffer. Besides the
|
||||
<methodname>buffer</methodname> method, &ChannelBuffers; provides a
|
||||
lot of useful methods related with &ChannelBuffer;. Please refer to
|
||||
the API reference.
|
||||
lot of useful methods related to the &ChannelBuffer;. For more
|
||||
information, please refer to the API reference.
|
||||
</para>
|
||||
<para>
|
||||
On the other hand, it's a good idea to use static imports for
|
||||
On the other hand, it is a good idea to use static imports for
|
||||
&ChannelBuffers;:
|
||||
<programlisting>import static org.jboss.netty.buffer.&ChannelBuffers;.*;
|
||||
...
|
||||
@ -392,19 +392,19 @@ public class TimeServerHandler extends &SimpleChannelHandler; {
|
||||
<para>
|
||||
But wait, where's the <methodname>flip</methodname>? Didn't we used
|
||||
to call <methodname>ByteBuffer.flip()</methodname> before sending a
|
||||
message in NIO? &ChannelBuffer; doesn't have such a method because
|
||||
message in NIO? &ChannelBuffer; does not have such a method because
|
||||
it has two pointers; one for read operations and the other for write
|
||||
operations. The writer index increases when you write something to
|
||||
a &ChannelBuffer; while the reader index doesn't change. The reader
|
||||
a &ChannelBuffer; while the reader index does not change. The reader
|
||||
index and the writer index represents where the message starts and
|
||||
ends respectively.
|
||||
</para>
|
||||
<para>
|
||||
In contrast, NIO buffer doesn't provide a clean way to figure out
|
||||
In contrast, NIO buffer does not provide a clean way to figure out
|
||||
where the message content starts and ends without calling the
|
||||
<methodname>flip</methodname> method. You will be in trouble when
|
||||
you forget to flip the buffer because nothing or incorrect data will
|
||||
be sent. Such an error doesn't happen in Netty because we have
|
||||
be sent. Such an error does not happen in Netty because we have
|
||||
different pointer for different operation types. You will find it
|
||||
makes your life much easier as you get used to it -- a life without
|
||||
flipping out!
|
||||
@ -412,7 +412,7 @@ public class TimeServerHandler extends &SimpleChannelHandler; {
|
||||
<para>
|
||||
Another point to note is that the <methodname>write</methodname>
|
||||
method returns a &ChannelFuture;. A &ChannelFuture; represents an
|
||||
I/O operation which was not occurred yet. It means, any requested
|
||||
I/O operation which has not yet occurred. It means, any requested
|
||||
operation might not have been performed yet because all operations
|
||||
are asynchronous in Netty. For example, the following code might
|
||||
close the connection even before a message is sent:
|
||||
@ -424,7 +424,7 @@ ch.close();</programlisting>
|
||||
Therefore, you need to call the <methodname>close</methodname>
|
||||
method after the &ChannelFuture;, which was returned by the
|
||||
<methodname>write</methodname> method, notifies you when the write
|
||||
operation has been done. Also, <methodname>close</methodname>
|
||||
operation has been done. Please note that, <methodname>close</methodname>
|
||||
might not close the connection immediately, and it returns a
|
||||
&ChannelFuture;.
|
||||
</para>
|
||||
@ -432,7 +432,7 @@ ch.close();</programlisting>
|
||||
<callout arearefs="example.time.co4">
|
||||
<para>
|
||||
How do we get notified when the write request is finished then?
|
||||
It's as simple as adding a &ChannelFutureListener; to the returned
|
||||
This is as simple as adding a &ChannelFutureListener; to the returned
|
||||
&ChannelFuture;. Here, we created a new anonymous &ChannelFutureListener;
|
||||
which closes the &Channel; when the operation is done.
|
||||
</para>
|
||||
@ -449,9 +449,9 @@ ch.close();</programlisting>
|
||||
<title>Writing a Time Client</title>
|
||||
<para>
|
||||
Unlike DISCARD and ECHO servers, we need a client for the TIME protocol
|
||||
because a human can't translate a 32-bit binary data into a date on a
|
||||
calendar. Let's make sure the server works correctly and learn how to
|
||||
write a client with Netty.
|
||||
because a human cannot translate a 32-bit binary data into a date on a
|
||||
calendar. In this section, we discuss how to make sure the server works
|
||||
correctly and learn how to write a client with Netty.
|
||||
</para>
|
||||
<para>
|
||||
The biggest and only difference between a server and a client in Netty
|
||||
@ -500,7 +500,7 @@ public class TimeClient {
|
||||
<callout arearefs="example.time2.co3">
|
||||
<para>
|
||||
Please note that there's no <literal>"child."</literal> prefix.
|
||||
A client-side &SocketChannel; doesn't have a parent.
|
||||
A client-side &SocketChannel; does not have a parent.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.time2.co4">
|
||||
@ -511,10 +511,10 @@ public class TimeClient {
|
||||
</callout>
|
||||
</calloutlist>
|
||||
<para>
|
||||
As you saw, it's not really different from the server side startup. What
|
||||
about the &ChannelHandler; implementation? It should receive a 32-bit
|
||||
integer from the server, translate it into a human readable format, print
|
||||
the translated time, and close the connection:
|
||||
As you can see, it is not really different from the server side startup.
|
||||
What about the &ChannelHandler; implementation? It should receive a
|
||||
32-bit integer from the server, translate it into a human readable format,
|
||||
print the translated time, and close the connection:
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.time;
|
||||
|
||||
@ -536,10 +536,10 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||
}
|
||||
}</programlisting>
|
||||
<para>
|
||||
It looks very simple and doesn't look any different from the server side
|
||||
It looks very simple and does not look any different from the server side
|
||||
example. However, this handler sometimes will refuse to work raising an
|
||||
<exceptionname>IndexOutOfBoundsException</exceptionname>. Let's figure
|
||||
out why in the next section.
|
||||
<exceptionname>IndexOutOfBoundsException</exceptionname>. We discuss why
|
||||
this happens in the next section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -554,20 +554,20 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||
<para>
|
||||
In a stream-based transport such as TCP/IP, packets can be fragmented and
|
||||
reassembled during transmission even in a LAN environment. For example,
|
||||
let's assume you have received three packets:
|
||||
let us assume you have received three packets:
|
||||
</para>
|
||||
<programlisting>+-----+-----+-----+
|
||||
| ABC | DEF | GHI |
|
||||
+-----+-----+-----+</programlisting>
|
||||
<para>
|
||||
because of the packet fragmentation, a server can receive them like the
|
||||
following:
|
||||
because of the packet fragmentation, a server can receive them as
|
||||
follows:
|
||||
</para>
|
||||
<programlisting>+----+-------+---+---+
|
||||
| AB | CDEFG | H | I |
|
||||
+----+-------+---+---+</programlisting>
|
||||
<para>
|
||||
Therefore, a receiving part, regardless it's server-side or client-side,
|
||||
Therefore, a receiving part, regardless it is server-side or client-side,
|
||||
should defrag the received packets into one or more meaningful
|
||||
<firstterm>frames</firstterm> that could be easily understood by the
|
||||
application logic. In case of the example above, the received packets
|
||||
@ -582,17 +582,17 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||
The First Solution
|
||||
</title>
|
||||
<para>
|
||||
Now let's get back to the TIME client example. We have the same problem
|
||||
Now let us get back to the TIME client example. We have the same problem
|
||||
here. A 32-bit integer is a very small amount of data, and it is not
|
||||
likely to be fragmented often. However, the problem is that it
|
||||
<emphasis>can</emphasis> be fragmented, and the possibility of
|
||||
fragmentation will increase as the traffic goes higher.
|
||||
fragmentation will increase as the traffic increases.
|
||||
</para>
|
||||
<para>
|
||||
The simplistic solution is to create an internal cumulative buffer and
|
||||
wait until all 4 bytes are received into the internal buffer. Here's
|
||||
the modified <classname>TimeClientHandler</classname> implementation
|
||||
that fixes the problem.
|
||||
wait until all 4 bytes are received into the internal buffer. The
|
||||
following is the modified <classname>TimeClientHandler</classname>
|
||||
implementation that fixes the problem:
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.time;
|
||||
|
||||
@ -630,7 +630,7 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||
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 messed up.
|
||||
the content of the <varname>buf</varname> will be corrupted.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.time3.co2">
|
||||
@ -657,11 +657,11 @@ public class TimeClientHandler extends &SimpleChannelHandler; {
|
||||
</callout>
|
||||
</calloutlist>
|
||||
<para>
|
||||
There's another place that needs a fix. Do you remember that we have
|
||||
There's another place that needs a fix. Do you remember that we
|
||||
added a <classname>TimeClientHandler</classname> instance to the
|
||||
<emphasis>default</emphasis> &ChannelPipeline; of the &ClientBootstrap;?
|
||||
It means one <classname>TimeClientHandler</classname> is going to handle
|
||||
multiple &Channel;s and consequently the data will be messed up. To
|
||||
multiple &Channel;s and consequently the data will be corrupted. To
|
||||
create a new <classname>TimeClientHandler</classname> instance per
|
||||
&Channel;, we should implement a &ChannelPipelineFactory;:
|
||||
</para>
|
||||
@ -676,7 +676,7 @@ public class TimeClientPipelineFactory implements &ChannelPipelineFactory; {
|
||||
}
|
||||
}</programlisting>
|
||||
<para>
|
||||
Now let's replace the following lines of <classname>TimeClient</classname>:
|
||||
Now let us replace the following lines of <classname>TimeClient</classname>:
|
||||
</para>
|
||||
<programlisting>TimeClientHandler handler = new TimeClientHandler();
|
||||
bootstrap.getPipeline().addLast("handler", handler);</programlisting>
|
||||
@ -702,17 +702,17 @@ bootstrap.getPipeline().addLast("handler", handler);</programlisting>
|
||||
</title>
|
||||
<para>
|
||||
Although the first solution has resolved the problem with the TIME
|
||||
client, the modified handler doesn't look that clean. Imagine a more
|
||||
client, the modified handler does not look that clean. Imagine a more
|
||||
complicated protocol which is composed of multiple fields such as a
|
||||
variable length field. Your &ChannelHandler; implementation will
|
||||
become unmaintainable very quickly.
|
||||
</para>
|
||||
<para>
|
||||
As you already might have noticed, you can add more than one
|
||||
&ChannelHandler; to a &ChannelPipeline;, and therefore, you can
|
||||
split one monolithic &ChannelHandler; into multiple modular ones to
|
||||
reduce the complexity of your application. For example, you could
|
||||
split <classname>TimeClientHandler</classname> into two handlers:
|
||||
As you may have noticed, you can add more than one &ChannelHandler; to
|
||||
a &ChannelPipeline;, and therefore, you can split one monolithic
|
||||
&ChannelHandler; into multiple modular ones to reduce the complexity of
|
||||
your application. For example, you could split
|
||||
<classname>TimeClientHandler</classname> into two handlers:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -764,8 +764,8 @@ public class TimeDecoder extends &FrameDecoder; {
|
||||
<callout arearefs="example.time4.co3">
|
||||
<para>
|
||||
If <literal>null</literal> is returned, it means there's not
|
||||
enough data yet. &FrameDecoder; will call again when more data is
|
||||
in.
|
||||
enough data yet. &FrameDecoder; will call again when there is a
|
||||
sufficient amount of data.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="example.time4.co3">
|
||||
@ -781,7 +781,7 @@ public class TimeDecoder extends &FrameDecoder; {
|
||||
</callout>
|
||||
</calloutlist>
|
||||
<para>
|
||||
If you are a adventurous person, you might want to try the
|
||||
If you are an adventurous person, you might want to try the
|
||||
&ReplayingDecoder; which simplifies the decoder even more. You will
|
||||
need to consult the API reference for more information though.
|
||||
</para>
|
||||
@ -798,10 +798,9 @@ public class TimeDecoder extends &ReplayingDecoder;<&VoidEnum;> {
|
||||
}</programlisting>
|
||||
<para>
|
||||
Additionally, Netty provides out-of-the-box decoders which enables
|
||||
you to implement most protocol very easily and helps you avoid from
|
||||
you to implement most protocols very easily and helps you avoid from
|
||||
ending up with a monolithic unmaintainable handler implementation.
|
||||
You might want to take a look into the following packages for more
|
||||
detailed examples:
|
||||
Please refer to the following packages for more detailed examples:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -825,9 +824,9 @@ public class TimeDecoder extends &ReplayingDecoder;<&VoidEnum;> {
|
||||
Speaking in POJO instead of ChannelBuffer
|
||||
</title>
|
||||
<para>
|
||||
All the examples we visited so far used a &ChannelBuffer; as a primary
|
||||
data structure of a protocol message. In this section, we will improve
|
||||
the TIME protocol client and server example to use a
|
||||
All the examples we have reviewed so far used a &ChannelBuffer; as a
|
||||
primary data structure of a protocol message. In this section, we will
|
||||
improve the TIME protocol client and server example to use a
|
||||
<ulink url="http://en.wikipedia.org/wiki/POJO">POJO</ulink> instead of a
|
||||
&ChannelBuffer;.
|
||||
</para>
|
||||
@ -836,12 +835,12 @@ public class TimeDecoder extends &ReplayingDecoder;<&VoidEnum;> {
|
||||
your handler becomes more maintainable and reusable by separating the
|
||||
code which extracts information from &ChannelBuffer; out from the
|
||||
handler. In the TIME client and server examples, we read only one
|
||||
32-bit integer and it's not a big deal to use &ChannelBuffer; directly.
|
||||
32-bit integer and it is not a major issue to use &ChannelBuffer; directly.
|
||||
However, you will find it is necessary to make the separation as you
|
||||
implement a real world protocol.
|
||||
</para>
|
||||
<para>
|
||||
First, let's define a new type called <classname>UnixTime</classname>.
|
||||
First, let us define a new type called <classname>UnixTime</classname>.
|
||||
</para>
|
||||
<programlisting>package org.jboss.netty.example.time;
|
||||
|
||||
@ -887,7 +886,7 @@ protected Object decode(
|
||||
</calloutlist>
|
||||
<para>
|
||||
With the updated decoder, the <classname>TimeClientHandler</classname>
|
||||
doesn't use &ChannelBuffer; anymore:
|
||||
does not use &ChannelBuffer; anymore:
|
||||
</para>
|
||||
<programlisting>@Override
|
||||
public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
@ -897,7 +896,7 @@ public void messageReceived(&ChannelHandlerContext; ctx, &MessageEvent; e) {
|
||||
}</programlisting>
|
||||
<para>
|
||||
Much simpler and elegant, right? The same technique can be applied on
|
||||
the server side. Let's update the
|
||||
the server side. Let us update the
|
||||
<classname>TimeServerHandler</classname> first this time:
|
||||
</para>
|
||||
<programlisting>@Override
|
||||
@ -963,7 +962,7 @@ public class TimeEncoder implements &SimpleChannelHandler; {
|
||||
in the &ChannelPipeline;.
|
||||
</para>
|
||||
<para>
|
||||
On the other hand, it's a good idea to use static imports for
|
||||
On the other hand, it is a good idea to use static imports for
|
||||
&Channels;:
|
||||
<programlisting>import static org.jboss.netty.channel.&Channels;.*;
|
||||
...
|
||||
@ -975,7 +974,7 @@ fireChannelDisconnected(ctx, e.getChannel());</programlisting>
|
||||
</calloutlist>
|
||||
<para>
|
||||
The last task left is to insert a <classname>TimeEncoder</classname>
|
||||
into the &ChannelPipeline; on the server side, and it's left as a
|
||||
into the &ChannelPipeline; on the server side, and it is left as a
|
||||
trivial exercise.
|
||||
</para>
|
||||
</section>
|
||||
@ -985,12 +984,11 @@ fireChannelDisconnected(ctx, e.getChannel());</programlisting>
|
||||
Summary
|
||||
</title>
|
||||
<para>
|
||||
In this chapter, we had a quick tour of Netty so that you can start to
|
||||
write a network application on top of Netty right away. I believe you
|
||||
still have a lot of questions about various topics, and they will be
|
||||
covered in the upcoming chapters and the revised version of this chapter.
|
||||
Also, please don't forget that <ulink url="&Community;">the Netty project
|
||||
community</ulink> is always here to help you.
|
||||
In this chapter, we had a quick tour of Netty with a demonstration on how
|
||||
to write a network application on top of Netty. More questions you may
|
||||
have will be covered in the upcoming chapters and the revised version of
|
||||
this chapter. Please also note that <ulink url="&Community;">the Netty
|
||||
project community</ulink> is always here to help you.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
Loading…
Reference in New Issue
Block a user