zoukankan      html  css  js  c++  java
  • netty写Echo Server & Client完整步骤教程(图文)

    1.创建Maven工程

     

     

     

     

     

     

     

     

     

    1.1 父节点的pom.xml代码(root pom文件)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <modelVersion>4.0.0</modelVersion>
     6 
     7     <groupId>org.example</groupId>
     8     <artifactId>echo_netty</artifactId>
     9     <packaging>pom</packaging>
    10     <version>1.0-SNAPSHOT</version>
    11     <modules>
    12         <module>netty-server</module>
    13         <module>netty-client</module>
    14     </modules>
    15     
    16 </project>

    1.2 子工程netty-server的pom.xml文件代码

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <parent>
     6         <artifactId>echo_netty</artifactId>
     7         <groupId>org.example</groupId>
     8         <version>1.0-SNAPSHOT</version>
     9     </parent>
    10     <modelVersion>4.0.0</modelVersion>
    11 
    12     <artifactId>netty-server</artifactId>
    13 
    14 
    15 </project>

    1.3 子工程netty-client的pom.xml文件代码

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <parent>
     6         <artifactId>echo_netty</artifactId>
     7         <groupId>org.example</groupId>
     8         <version>1.0-SNAPSHOT</version>
     9     </parent>
    10     <modelVersion>4.0.0</modelVersion>
    11 
    12     <artifactId>netty-client</artifactId>
    13 
    14 
    15 </project>

    1.4 修改父工程的pom.xml,修改后如下所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <modelVersion>4.0.0</modelVersion>
     6 
     7     <groupId>org.example</groupId>
     8     <artifactId>echo_netty</artifactId>
     9     <packaging>pom</packaging>
    10     <version>1.0-SNAPSHOT</version>
    11     <modules>
    12         <module>netty-server</module>
    13         <module>netty-client</module>
    14     </modules>
    15 
    16     <properties>
    17         <echo-server.hostname>localhost</echo-server.hostname>
    18         <echo-server.port>9999</echo-server.port>
    19     </properties>
    20 
    21     <dependencies>
    22         <dependency>
    23             <groupId>io.netty</groupId>
    24             <artifactId>netty-all</artifactId>
    25             <version>4.1.10.Final</version>
    26             <scope>compile</scope>
    27         </dependency>
    28     </dependencies>
    29 
    30     <build>
    31         <plugins>
    32             <plugin>
    33                 <artifactId>maven-compiler-plugin</artifactId>
    34             </plugin>
    35             <plugin>
    36                 <artifactId>maven-failsafe-plugin</artifactId>
    37             </plugin>
    38             <plugin>
    39                 <artifactId>maven-surefire-plugin</artifactId>
    40             </plugin>
    41             <plugin>
    42                 <groupId>org.codehaus.mojo</groupId>
    43                 <artifactId>exec-maven-plugin</artifactId>
    44             </plugin>
    45         </plugins>
    46     </build>
    47 </project>

    1.5 修改netty-server的pom.xml,修改后如下所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <parent>
     6         <artifactId>echo_netty</artifactId>
     7         <groupId>org.example</groupId>
     8         <version>1.0-SNAPSHOT</version>
     9     </parent>
    10     <modelVersion>4.0.0</modelVersion>
    11 
    12     <artifactId>netty-server</artifactId>
    13 
    14     <build>
    15         <plugins>
    16             <plugin>
    17                 <groupId>org.codehaus.mojo</groupId>
    18                 <artifactId>exec-maven-plugin</artifactId>
    19                 <executions>
    20                     <execution>
    21                         <id>run-server</id>
    22                         <goals>
    23                             <goal>java</goal>
    24                         </goals>
    25                     </execution>
    26                 </executions>
    27                 <configuration>
    28                     <mainClass>com.echo.server.EchoServer</mainClass>
    29                     <arguments>
    30                         <argument>${echo-server.port}</argument>
    31                     </arguments>
    32                 </configuration>
    33             </plugin>
    34         </plugins>
    35     </build>
    36 
    37 </project>

    1.6 修改netty-client的pom.xml,修改后如下所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <parent>
     6         <artifactId>echo_netty</artifactId>
     7         <groupId>org.example</groupId>
     8         <version>1.0-SNAPSHOT</version>
     9     </parent>
    10     <modelVersion>4.0.0</modelVersion>
    11 
    12     <artifactId>netty-client</artifactId>
    13 
    14     <build>
    15         <plugins>
    16             <plugin>
    17                 <groupId>org.codehaus.mojo</groupId>
    18                 <artifactId>exec-maven-plugin</artifactId>
    19                 <executions>
    20                     <execution>
    21                         <id>run-server</id>
    22                         <goals>
    23                             <goal>java</goal>
    24                         </goals>
    25                     </execution>
    26                 </executions>
    27                 <configuration>
    28                     <mainClass>com.echo.client.EchoClient</mainClass>
    29                     <arguments>
    30                         <argument>${echo-server.hostname}</argument>
    31                         <argument>${echo-server.port}</argument>
    32                     </arguments>
    33                 </configuration>
    34             </plugin>
    35         </plugins>
    36     </build>
    37 
    38 </project>

    2. 开始写netty客户端的代码

     

     

     

     

     

     到这里的时候,项目的结构应该是这个样子的,然后让我们修改一下EchoClient.java和EchoClientHandler.java文件的内容,修改后最终代码放在下面,大家请看:

    2.1 EchoClient.java的最终代码

     1 package com.echo.client;
     2 
     3 import java.net.InetSocketAddress;
     4 
     5 import com.echo.client.handler.EchoClientHandler;
     6 import io.netty.bootstrap.Bootstrap;
     7 import io.netty.channel.ChannelFuture;
     8 import io.netty.channel.ChannelInitializer;
     9 import io.netty.channel.EventLoopGroup;
    10 import io.netty.channel.nio.NioEventLoopGroup;
    11 import io.netty.channel.socket.SocketChannel;
    12 import io.netty.channel.socket.nio.NioSocketChannel;
    13 
    14 public class EchoClient {
    15 
    16     private final String host;
    17     private final int port;
    18 
    19     public EchoClient(String host, int port) {
    20         this.host = host;
    21         this.port = port;
    22     }
    23 
    24     public static void main(String[] args) throws Exception {
    25         if (args.length != 2) {
    26             System.err.println(
    27                     "Usage: " + EchoClient.class.getSimpleName() +
    28                             " <host> <port>");
    29             return;
    30         }
    31         String host = args[0];
    32         int port = Integer.parseInt(args[1]);
    33         new EchoClient(host, port).start();
    34     }
    35 
    36     public void start() throws Exception {
    37         EventLoopGroup group = new NioEventLoopGroup();
    38         try {
    39             Bootstrap b = new Bootstrap();
    40             b.group(group)
    41                     .channel(NioSocketChannel.class)
    42                     .remoteAddress(new InetSocketAddress(host, port))
    43                     .handler(new ChannelInitializer<SocketChannel>() {
    44 
    45                         @Override
    46                         protected void initChannel(SocketChannel ch) throws Exception {
    47                             ch.pipeline().addLast(new EchoClientHandler());
    48                         }
    49 
    50                     });
    51             ChannelFuture f = b.connect().sync();
    52             f.channel().closeFuture().sync();
    53         } finally {
    54             group.shutdownGracefully().sync();
    55         }
    56     }
    57 
    58 }

    2.2 EchoClientHandler.java的最终代码

     1 package com.echo.client.handler;
     2 
     3 import io.netty.buffer.ByteBuf;
     4 import io.netty.buffer.Unpooled;
     5 import io.netty.channel.ChannelHandler.Sharable;
     6 import io.netty.channel.ChannelHandlerContext;
     7 import io.netty.channel.SimpleChannelInboundHandler;
     8 import io.netty.util.CharsetUtil;
     9 
    10 @Sharable
    11 public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
    12 
    13     @Override
    14     public void channelActive(ChannelHandlerContext ctx) throws Exception {
    15         ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
    16     }
    17 
    18     @Override
    19     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    20         System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8));
    21     }
    22 
    23     @Override
    24     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    25         cause.printStackTrace();
    26         ctx.close();
    27     }
    28 
    29 }

    到这的时候,如果有报错的话,一般是maven没有刷新导致的。

    解决方法是,打开父工程的pom.xml ,然后点击idea的右侧的maven刷新按钮,如下图所示

     至此,EchoClient端的代码就写好了。暂时先不启动,先写好EchoServer,再一起启动。下面介绍EchoServer端的代码。

    3. 开始写netty服务端的代码

    3.2 修改EchoServer.java文件代码,修改后最终代码如下:

     1 package com.echo.server;
     2 
     3 import java.net.InetSocketAddress;
     4 
     5 import com.echo.server.handler.EchoServerHandler;
     6 import io.netty.bootstrap.ServerBootstrap;
     7 import io.netty.channel.ChannelFuture;
     8 import io.netty.channel.ChannelInitializer;
     9 import io.netty.channel.EventLoopGroup;
    10 import io.netty.channel.nio.NioEventLoopGroup;
    11 import io.netty.channel.socket.SocketChannel;
    12 import io.netty.channel.socket.nio.NioServerSocketChannel;
    13 
    14 public class EchoServer {
    15 
    16     private final int port;
    17 
    18     public EchoServer(int port) {
    19         this.port = port;
    20     }
    21 
    22     public void start() throws Exception {
    23         final EchoServerHandler serverHandler = new EchoServerHandler();
    24         EventLoopGroup group = new NioEventLoopGroup();
    25         try {
    26             ServerBootstrap b = new ServerBootstrap();
    27             b.group(group)
    28                     .channel(NioServerSocketChannel.class)
    29                     .localAddress(new InetSocketAddress(port))
    30                     .childHandler(new ChannelInitializer<SocketChannel>() {
    31 
    32                         @Override
    33                         protected void initChannel(SocketChannel ch) throws Exception {
    34                             ch.pipeline().addLast(serverHandler);
    35                         }
    36                     });
    37             // 此处绑定服务器,并等待绑定完成。对sync()方法的调用将导致当前Thread阻塞,直到绑定完成
    38             ChannelFuture f = b.bind().sync();
    39             // 由于调用了sync()方法,程序将会阻塞等待,直到服务器的Channel关闭
    40             f.channel().closeFuture().sync();
    41         } finally {
    42             group.shutdownGracefully().sync();
    43         }
    44     }
    45 
    46     public static void main(String[] args) throws Exception {
    47         if (args.length != 1) {
    48             System.err.println(
    49                     "Usage: " + EchoServer.class.getSimpleName() + " <port>"
    50             );
    51             return;
    52         }
    53         int port = Integer.parseInt(args[0]);
    54         new EchoServer(port).start();
    55     }
    56 
    57 }

    3.3 修改EchoServerHandler.java文件代码,修改后最终代码如下:

     1 package com.echo.server.handler;
     2 
     3 import io.netty.buffer.ByteBuf;
     4 import io.netty.buffer.Unpooled;
     5 import io.netty.channel.ChannelHandler.Sharable;
     6 import io.netty.channel.ChannelFutureListener;
     7 import io.netty.channel.ChannelHandlerContext;
     8 import io.netty.channel.ChannelInboundHandlerAdapter;
     9 import io.netty.util.CharsetUtil;
    10 
    11 // @Sharable标示一个ChannelHandler可以被多个Channel安全共享
    12 @Sharable
    13 public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    14 
    15     @Override
    16     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    17         ByteBuf in = (ByteBuf) msg;
    18         System.out.println(
    19                 "Server received: " + in.toString(CharsetUtil.UTF_8));
    20         // 将接收到的消息写给发送者,即客户端,而不冲刷出站消息
    21         ctx.write(in);
    22     }
    23 
    24     @Override
    25     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    26         // 将未决消息冲刷到远程节点,并且关闭该Channel
    27         ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
    28                 .addListener(ChannelFutureListener.CLOSE);
    29     }
    30 
    31     @Override
    32     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    33         cause.printStackTrace();
    34         ctx.close();
    35     }
    36 
    37 }

    至此,所有的代码已经写好,下一步进行运行测试

    4.运行代码

    4.1 打包代码

     

     当出现BUILD SUCCESS的时候,代表代码已经打包好了。

    4.2 运行server端

     

     出现一直在转圈的时候,代表server端启动成功了

    4.3 运行client端

     双击运行client端,然后稍等片刻,会发现下图已经出现了

    Client received: Netty rocks!

    这一行字。说明客户端和服务端通信成功。

     接着看一下server端打印的输出,如下图:

    可以看到,server端已经输出了从客户端收到的消息!!!

    至此,所有的演示都结束了,大家自己动手进行实践吧。

  • 相关阅读:
    【python】一个文件内容写入另一个
    【Linux】批量修改权限
    【Git】git add git commit
    赌博游戏
    输出斐波那契数列前20项,每输出5个数换行
    Java线程的几种可用状态
    Java创建线程的方式
    Java虚拟机
    判断对象oStringObject是否为String
    throw跟throws关键字
  • 原文地址:https://www.cnblogs.com/lukairui/p/13802639.html
Copyright © 2011-2022 走看看