Now that we are getting started, let's write a simple Demo here. The client sends a string to the server, and the server receives the string and sends it back to the client.
2.1 configure the development environment
1. Install JDK2. download the jar package from the official website (or build it through pom)
2.2 understand Netty's Client and ServerA Netty application model, as shown in, but you need to understand that the Server we write will automatically process multiple client requests. Theoretically, the ability to process concurrency depends on our system configuration and the JDK limit. VcXUo6y + latest/latest + zvHG97XEz + latest/J0tTA67 + qo6y + zbT6se22z7 + latest/vDx7XEurDJ + latest/latest + latest 8rbSmwO0KPHN0cm9uZz4yLjMuMSBCb290c1RyYXBwaW5ntcS5/bpmow.vc3ryb25npgo8chjlignsyxnzpq = "brush: java; "> package NettyDemo. echo. server; import io. netty. bootstrap. serverBootstrap; import io. netty. channel. channelFuture; import io. netty. channel. channelInitializer; import io. netty. channel. eventLoopGroup; import io. netty. channel. nio. nioEventLoopGroup; import io. netty. channel. socket. socketChannel; import io. netty. channel. socket. nio. nioServerSocketChannel; import java.net. inetSocketAddress; import NettyDemo. echo. handler. echoServerHandler; public class EchoServer {private static final int port = 8080; public void start () throws InterruptedException {ServerBootstrap B = new ServerBootstrap (); // Bootstrap helper EventLoopGroup group = new NioEventLoopGroup (); // receives and processes connections in nio mode try {B. group (group); B. channel (NioServerSocketChannel. class); // set the nio-type channelb. localAddress (new InetSocketAddress (port); // set listening port B. childHandler (new ChannelInitializer () {// A channelprotected void initChannel (SocketChannel ch) throws Exception will be created when a connection is established {// Handler in the pipeline management channel, add a handler to the channel queue to process the ch. pipeline (). addLast ("myHandler", new EchoServerHandler () ;}}); ChannelFuture f = B. bind (). sync (); // After the configuration is complete, bind the server and call the sync synchronization method until the System is successfully bound. out. println (EchoServer. class. getName () + "started and listen on" + f. channel (). localAddress (); f. channel (). closeFuture (). sync (); // The application will wait until the channel is closed} catch (Exception e) {e. printStackTrace ();} finally {group. shutdownGracefully (). sync (); // close EventLoopGroup and release all resources including the created thread} public static void main (String [] args) {try {new EchoServer (). start ();} catch (InterruptedException e) {e. printStackTrace ();}}}1. Create a ServerBootstrap instance
2. Create an EventLoopGroup to process various events, such as handling link requests and sending and receiving data.
3. Define the local InetSocketAddress (port) to bind the Server
4. Create childHandler to process each link request
5. Call the ServerBootstrap. bind () method to bind the Server after all preparations
2.3.2 business logic ServerHandler:
To process received data, we must inherit the ChannelInboundHandlerAdapter interface and rewrite the MessageReceive method in it. This method is called whenever data arrives (usually Byte arrays ), here we write our business logic:
Package NettyDemo. echo. handler; import io. netty. buffer. unpooled; import io. netty. channel. channelFutureListener; import io. netty. channel. channelHandlerContext; import io. netty. channel. channelInboundHandlerAdapter; import io. netty. channel. channelHandler. sharable; /*** Sharable indicates that this object is shared among channels * handler class is our specific service class **/@ Sharable // annotation @ Sharable allows it to share public class EchoServerHandler among channels extends ChannelInboundHandlerAdapter {public void channelRead (ChannelHandlerContext ctx, object msg) {System. out. println ("server received ed data:" + msg); ctx. write (msg); // write back data,} public void channelReadComplete (ChannelHandlerContext ctx) {ctx. writeAndFlush (Unpooled. EMPTY_BUFFER) // flush all written data. addListener (ChannelFutureListener. CLOSE); // CLOSE channel} public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause) {cause. printStackTrace (); // capture the exception information ctx. close (); // close the channel when an exception occurs }}
2.3.3 exception handling:
We have also rewritten the exceptionCaught method in the above program, which is used to handle exceptions.
2.4 write a Netty Client
Generally, a simple Client will assume the following role: connect to the Server and write data to the Server. Wait for the Server to return data to close the connection.
4.4.1 BootsTrapping process:
Similar to the Server, the Client must specify the IP address and Port used to connect to the host at the same time.
package NettyDemo.echo.client;import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import java.net.InetSocketAddress;import NettyDemo.echo.handler.EchoClientHandler;public class EchoClient {private final String host;private final int port;public EchoClient(String host, int port) {this.host = host;this.port = port;}public void start() throws Exception {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group);b.channel(NioSocketChannel.class);b.remoteAddress(new InetSocketAddress(host, port));b.handler(new ChannelInitializer
() {public void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});ChannelFuture f = b.connect().sync();f.addListener(new ChannelFutureListener() {public void operationComplete(ChannelFuture future) throws Exception {if(future.isSuccess()){System.out.println("client connected");}else{System.out.println("server attemp failed");future.cause().printStackTrace();}}});f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws Exception {new EchoClient("127.0.0.1", 3331).start();}}
1. Create a ServerBootstrap instance
2. Create an EventLoopGroup to process various events, such as handling link requests and sending and receiving data.
3. Define a remote InetSocketAddress for client connection
4. After the connection is complete, Handler will be executed once.
5. Call the ServerBootstrap. connect () method to connect to the Server after all preparations
4.4.2 business logic ClientHandler:
We also inherit a SimpleChannelInboundHandler to implement our Client. We need to rewrite the three methods:
Package NettyDemo. echo. handler; import io. netty. buffer. byteBuf; import io. netty. buffer. byteBufUtil; import io. netty. buffer. unpooled; import io. netty. channel. channelHandlerContext; import io. netty. channel. simpleChannelInboundHandler; import io. netty. channel. channelHandler. sharable; import io. netty. util. charsetUtil; @ Sharablepublic class EchoClientHandler extends SimpleChannelInboundHandler
{/*** This method will be called after the server is connected **/public void channelActive (ChannelHandlerContext ctx) {ctx. write (Unpooled. copiedBuffer ("Netty rocks! ", CharsetUtil. UTF_8);}/*** this method will call **/public void channelRead0 (ChannelHandlerContext ctx, ByteBuf in) {System. out. println ("Client received:" + ByteBufUtil. hexDump (in. readBytes (in. readableBytes ();}/*** caught exception **/public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause) {cause. printStackTrace (); ctx. close ();}}
Note that the channelRead0 () method receives some data fragments. For example, if the server sends 5 bytes of data, the Client cannot guarantee that all data is received at a time, for example, 3 bytes are received for the first time and 2 bytes are received for the second time. We may also be concerned about whether the sending sequence of the received fragments is consistent, depending on the specific Protocol. For example, the byte stream based on the TCP protocol can ensure the order. Another point is that our business Handler inherits SimpleChannelInboundHandler on the Client side, and the ChannelInboundHandlerAdapter inherits from the server side. What are the differences between the two? The main difference is that SimpleChannelInboundHandler will automatically release the Bytebuffer resources occupied by data after receiving the data (automatically call Bytebuffer. release ()). Why can't the server be used? Because we want the server to send the data requested by the client back, the server may not write the data before the channelRead method returns, therefore, it cannot be automatically release.