Synchronize the original text to http://www.waylau.com/netty-chat/
Netty is a Java NIO Client server framework that allows you to quickly and easily develop network applications such as server and client protocols. Netty greatly simplifies the development of network programs such as the development of TCP and UDP socket services. For more information on Netty, refer to the Netty 4.x User Guide (https://github.com/waylau/netty-4-user-guide)
Below, fast implementation of a chat applet based on Netty.
Get ready
- JDK 7+
- Maven 3.2.x
- Netty 4.x
- Eclipse 4.x
Service side
Let's start with the implementation of the handler (processor), handler is generated by Netty to handle I/O events.
Simplechatserverhandler.java
public class Simplechatserverhandler extends simplechannelinboundhandler<string> {//(1) public static CHANNELGR OUP channels = new Defaultchannelgroup (globaleventexecutor.instance); @Override public void handleradded (Channelhandlercontext ctx) throws Exception {//(2) Channel incoming = CTX. Channel (); for (Channel channel:channels) {Channel.writeandflush ("[SERVER]-" + incoming.remoteaddress () + "add \ n"); } channels.add (Ctx.channel ()); } @Override public void handlerremoved (Channelhandlercontext ctx) throws Exception {//(3) Channel incoming = Ctx.channel (); for (Channel channel:channels) {Channel.writeandflush ("[SERVER]-" + incoming.remoteaddress () + "leave \ n"); } channels.remove (Ctx.channel ()); } @Override protected void channelRead0 (Channelhandlercontext ctx, String s) throws Exception {//(4) Channe L incoming = Ctx.channel (); for (channel Channel : Channels) {if (Channel! = incoming) {Channel.writeandflush ("[" + incoming.remoteaddress () + "]" + S + "\ n"); } else {Channel.writeandflush ("[You]" + S + "\ n"); }}} @Override public void channelactive (Channelhandlercontext ctx) throws Exception {//(5) Chan Nel incoming = Ctx.channel (); System.out.println ("Simplechatclient:" +incoming.remoteaddress () + "online"); } @Override public void channelinactive (Channelhandlercontext ctx) throws Exception {//(6) Channel incoming = Ctx.channel (); System.out.println ("Simplechatclient:" +incoming.remoteaddress () + "drop Line"); } @Override public void Exceptioncaught (Channelhandlercontext ctx, throwable cause) {//(7) Channel incoming = Ctx.channel (); System.out.println ("Simplechatclient:" +incoming.remoteaddress () + "exception"); When an exception occurs, close the connection cause.printstacktrace (); Ctx.close (); }}
1.SimpleChatServerHandler inherits from Simplechannelinboundhandler, this class implements the Channelinboundhandler interface, Channelinboundhandler Provides a number of interface methods for event handling, and then you can override these methods. Now it is only necessary to inherit the Simplechannelinboundhandler class instead of implementing the interface method yourself.
2. Overwrite the handleradded () event handling method. Whenever a new client connection is received from the server, the client's channel is deposited in the Channelgroup list and the other client channel in the notification list
3. Overwrite the handlerremoved () event handling method. Whenever a client is disconnected from the server, the client's channel is removed from the Channelgroup list and the other client channel in the notification list is
4. Overwrite the channelRead0 () event handling method. Forwards information to the Channel of other clients whenever the client writes information from the server. If you are using the Netty 5.x version, you need to rename channelRead0 () to Messagereceived ()
5. Overwrite the channelactive () event handling method. Service-side monitor hears client activity
6. Overwrite the channelinactive () event handling method. Service-side supervisor hears client inactive
The 7.exceptionCaught () event processing method is called when a Throwable object occurs, that is, when Netty due to an IO error or when the processor throws an exception while processing an event. In most cases, the caught exception should be recorded and the associated channel closed. However, this approach can be handled differently when encountering different exceptions, such as a response message that you might want to send an error code before closing the connection.
Simplechatserverinitializer.java
Simplechatserverinitializer is used to add multiple processing classes to channelpipeline, including encoding, decoding, Simplechatserverhandler, and so on.
public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new SimpleChatServerHandler()); System.out.println("SimpleChatClient:"+ch.remoteAddress() +"连接上"); }}
Simplechatserver.java
Write a main () method to start the server.
public class Simplechatserver {private int port; public simplechatserver (int port) {this.port = port; } public void Run () throws Exception {Eventloopgroup bossgroup = new Nioeventloopgroup ();//(1) Eventlo Opgroup Workergroup = new Nioeventloopgroup (); try {serverbootstrap b = new Serverbootstrap ();//(2) B.group (Bossgroup, Workergroup) . Channel (Nioserversocketchannel.class)//(3). Childhandler (New Simplechatserverinitializer ())//(4) . option (Channeloption.so_backlog, +)//(5). Childoption (Channeloption.so_keepalive, true); (6) System.out.println ("Simplechatserver initiated"); Bind the port, start receiving incoming connections channelfuture f = b.bind (port). sync (); (7)//wait for the server socket to close. In this example, this will not happen, but you can gracefully shut down your server. F.channel (). Closefuture (). sync (); } finally {workergroup.shutdowngracefully (); Bossgroup.shutdowngracefully (); System.out.println ("Simplechatserver closed"); }} public static void Main (string[] args) throws Exception {int port; if (Args.length > 0) {port = Integer.parseint (Args[0]); } else {port = 8080; } new Simplechatserver (port). Run (); }}
The 1.NioEventLoopGroup is a multithreaded event circulator for I/O operations, and Netty provides many different implementations of Eventloopgroup to handle different transports. In this example we have implemented a service-side application, so there will be 2 nioeventloopgroup to be used. The first one is often called the ' boss ', which is used to receive incoming connections. The second is often called ' worker ', which is used to handle the connection that has been received, and once the ' boss ' receives the connection, it registers the connection information with the ' worker '. How to know how many threads have been used, how to map to the channel that has been created, depends on the implementation of Eventloopgroup, and can be configured by constructors to configure their relationships.
2.ServerBootstrap is a secondary startup class that initiates the NIO service. You can use the Channel directly in this service, but this can be a complex process, and in many cases you do not need to do so.
3. Here we specify the use of the Nioserversocketchannel class to illustrate how a new Channel receives incoming connections.
4. The event handler class here is often used to handle a recent Channel that has been received. Simplechatserverinitializer inherited from Channelinitializer is a special processing class whose purpose is to help users configure a new Channel. Perhaps you want to implement your network program by adding some processing classes like Simplechatserverhandler to configure a new Channel or its corresponding channelpipeline. When your program becomes complex, you might add more processing classes to pipline, and then extract those anonymous classes onto the topmost class.
5. You can set the configuration parameters specified here for the Channel implementation. We are writing a TCP/IP server, so we are allowed to set the socket parameter options such as Tcpnodelay and keepAlive. Please refer to the channeloption and detailed channelconfig implementation of the interface documentation so that you can have a general understanding of channeloption.
6.option () is provided to Nioserversocketchannel to receive incoming connections. Childoption () is provided to the connection received by the parent pipe Serverchannel, which is also nioserversocketchannel in this case.
7. We continue, and all that is left is to bind the port and start the service. Here we bind the machine to the 8080 ports on all the machine cards. Of course now you can call the bind () method multiple times (based on different binding addresses).
Congratulations! You have completed the Netty Chat Service-based program.
ClientSimplechatclienthandler.java
The client's processing class is relatively simple, just to print out the read information
public class SimpleChatClientHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { System.out.println(s); }}
Simplechatclientinitializer.java
Similar to the service side
public class SimpleChatClientInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new SimpleChatClientHandler()); }}
Simplechatclient.java
Write a main () method to start the client.
public class Simplechatclient {public static void main (string[] args) throws exception{new Simplechatclien T ("localhost", 8080). Run (); } private final String host; private final int port; Public Simplechatclient (String host, int port) {this.host = host; This.port = port; public void Run () throws exception{Eventloopgroup group = new Nioeventloopgroup (); try {Bootstrap Bootstrap = new Bootstrap (). Group (Group). C Hannel (Niosocketchannel.class). Handler (new Simplechatclientinitializer ()); Channel channel = Bootstrap.connect (host, port). Sync (). Channel (); BufferedReader in = new BufferedReader (new InputStreamReader (system.in)); while (true) {Channel.writeandflush (In.readline () + "\ r \ n"); }} catch (Exception e) { E.printstacktrace (); } finally {group.shutdowngracefully (); } } }}
Run effect
Run Simplechatserver First, then run multiple simplechatclient, console input text continue testing
Source
See Https://github.com/waylau/netty-4-user-guide-demos.simplechat
Reference
- Netty 4.x User Guide Https://github.com/waylau/netty-4-user-guide
Netty Realization Chat function