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端已經輸出了從客戶端收到的消息!!!

 

至此,所有的演示都結束了,大家自己動手進行實踐吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM