日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

问道Netty。持续更新。。。

發布時間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 问道Netty。持续更新。。。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概念

Zero Copy

  • 0拷貝,速度快
  • 操作數據時, 不需要將數據 buffer 從一個內存區域拷貝到另一個內存區域. 因為少了一次內存的拷貝, 因此 CPU 的效率就得到的提升.
  • 在 OS 層面上的 Zero-copy 通常指避免在 用戶態(User-space) 與 內核態(Kernel-space) 之間來回拷貝數據. 例如 Linux 提供的 mmap 系統調用, 它可以將一段用戶空間內存映射到內核空間, 當映射成功后, 用戶對這段內存區域的修改可以直接反映到內核空間; 同樣地, 內核空間對這段區域的修改也直接反映用戶空間. 正因為有這樣的映射關系, 我們就不需要在 用戶態(User-space) 與 內核態(Kernel-space) 之間拷貝數據, 提高了數據傳輸的效率.

而需要注意的是, Netty 中的 Zero-copy 與上面我們所提到到 OS 層面上的 Zero-copy 不太一樣, Netty的 Zero-coyp 完全是在用戶態(Java 層面)的, 它的 Zero-copy 的更多的是偏向于 優化數據操作 這樣的概念.

實操

代碼

服務器

新建Maven項目:

添加插件:

<plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution> <!-- // 可以添加對應的執行階段--><phase>test</phase> <!-- ...--><goals> <!-- // 指定來的 goal為java,表示運行java程序--><goal>java</goal></goals></execution></executions><configuration> <!-- // 指定了運行的main class--><mainClass>com.cc.netty.server.EchoServer</mainClass> <!-- // 執行運行 main class的參數--> <!-- // 其實就是傳入main方法的String[]--><arguments><argument>argument1</argument> <!-- ...--></arguments> <!-- // 運行java的程序的系統參數--><systemProperties><systemProperty><key>myproperty</key><value>myvalue</value></systemProperty> <!-- ...--></systemProperties></configuration></plugin>

執行mvn exec:java:
報錯:
說明插件里的參數有問題。

  • 不好用,用下面的簡單代碼:
  • 服務端:
package com.cc.netty.test;import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil;import java.util.Scanner;/*** netty服務端* NioEventLoopGroup是一個處理I/O操作的多線程事件循環。* Netty為不同類型的傳輸提供了各種EventLoopGroup實現。* 我們在這個例子中實現了一個服務器端應用程序,* 因此將使用兩個NioEventLoopGroup。第一個通常被稱為“boss”,接受傳入的連接。第二個通常稱為“worker”,* 在boss接受連接并將接受的連接注冊到worker之后,處理接受連接的流量。使用多少線程以及如何將它們映射到創建的通道取決于EventLoopGroup實現,* 甚至可以通過構造函數進行配置。* <p>* ServerBootstrap是一個設置服務器的助手類。您可以直接使用通道設置服務器。但是,請注意這是一個冗長的過程,在大多數情況下您不需要這樣做。* 在這里,我們指定使用NioServerSocketChannel類,該類用于實例化一個新通道以接受傳入連接。* <p>* 這里指定的處理程序總是由新接受的通道計算。ChannelInitializer是用于幫助用戶配置新通道的特殊處理程序。* 您很可能希望通過添加一些處理程序(如DiscardServerHandler)來實現您的網絡應用程序,來配置新通道的ChannelPipeline。* 隨著應用程序變得復雜,您可能會向管道中添加更多的處理程序,并最終將這個匿名類提取到頂級類中。* <p>* 您還可以設置特定于通道實現的參數。我們正在編寫TCP/IP服務器,因此我們可以設置套接字選項,如tcpNoDelay和keepAlive。* 請參閱ChannelOption的apidocs和特定的ChannelConfig實現,以獲得受支持的ChannelOptions的概述。* <p>* 你注意到option()和childOption()了嗎?option()用于接收傳入連接的NioServerSocketChannel。* childOption()用于父服務器通道接受的通道,在本例中是NioServerSocketChannel。* 我們現在準備好出發了。剩下的就是綁定到端口并啟動服務器。在這里,我們綁定到機器中所有NICs(網絡接口卡)的端口8080。* 現在,您可以任意次數地調用bind()方法(使用不同的綁定地址)。* <p>* telnet 可以測試服務器是否工作* telnet localhost 8080*/ public class NettyServer {public static void main(String[] args) throws Exception {new NettyServer().run(8666);}//新建一個netty服務器public void run(int port) throws Exception {//NioEventLoopGroup是一個處理I/O操作的多線程循環EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workGroup = new NioEventLoopGroup();System.out.println("準備運行端口:" + port);try {//服務器的設置助手類ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap = serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true)//這里指定的處理程序總是由新接受的通道計算。.childHandler(new ChildChannelHandler());//綁定端口,同步等待成功ChannelFuture future = serverBootstrap.bind(port).sync();//等待服務監聽端口關閉future.channel().closeFuture().sync();} finally {//退出,釋放線程資源workGroup.shutdownGracefully();bossGroup.shutdownGracefully();}} }//ChannelInitializer是用于幫助用戶配置新通道的特殊處理程序 class ChildChannelHandler extends ChannelInitializer<SocketChannel> {//請求到達后調用protected void initChannel(SocketChannel socketChannel) throws Exception { // ByteBuf byteBuf= Unpooled.copiedBuffer("$".getBytes()); // socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,byteBuf));socketChannel.pipeline().addLast(new StringDecoder());//進行字符串的編解碼設置socketChannel.pipeline().addLast(new StringEncoder());socketChannel.pipeline().addLast(new ReadTimeoutHandler(60));//設置超時時間socketChannel.pipeline().addLast(new DiscardServerHandler());} }/*** 服務器類型設置**/ class DiscardServerHandler extends ChannelHandlerAdapter {@Override//只要接收到數據,就會調用channelRead()方法public void channelRead(ChannelHandlerContext ctx, Object msg) {try {//ByteBuf是一個引用計數的對象,必須通過release()方法顯式地釋放它System.out.println(String.format("%s === %s","收到信息",msg)); // ByteBuf in = (ByteBuf) msg;System.out.println("傳輸內容是"); // System.out.println(in.toString(CharsetUtil.UTF_8));//返回信息ByteBuf resp = Unpooled.copiedBuffer("服務端收到信息,ack$".getBytes());ctx.writeAndFlush(resp); // Scanner scanner = Scanner.} finally {System.out.println(msg);ReferenceCountUtil.release(msg);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 出現異常就關閉cause.printStackTrace();ctx.close();}}
  • 客戶端:
package com.cc.netty.test;import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil;/*** netty 編寫的客戶端*/ public class TimeClient {public static void main(String[] args) throws Exception {new TimeClient().connect(8666, "localhost");}public void connect(int port, String host) throws Exception {//配置客戶端System.out.println("連接=>" + host + ":" + port);EventLoopGroup eventLoopGroup = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {protected void initChannel(SocketChannel socketChannel) throws Exception {ByteBuf byteBuf = Unpooled.copiedBuffer("$".getBytes());socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, byteBuf));socketChannel.pipeline().addLast(new TimeClientHandler());}});//綁定端口,同步等待成功ChannelFuture future = bootstrap.connect(host, port).sync();//等待服務監聽端口關閉future.channel().closeFuture().sync();} finally {//優雅退出,釋放線程資源eventLoopGroup.shutdownGracefully();}} }class TimeClientHandler extends ChannelHandlerAdapter {private byte[] req;public TimeClientHandler() {req = "中國必勝!武漢加油!".getBytes(); // req = "$tmb00035ET3318/08/22 11:5704026.75,027.31,20.00,20.00$".getBytes();}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf message = null;for (int i = 0; i < 5; i++) {message = Unpooled.buffer(req.length);message.writeBytes(req);ctx.writeAndFlush(message);}}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {try {ByteBuf in = (ByteBuf) msg;System.out.println(in.toString(CharsetUtil.UTF_8));} finally {ReferenceCountUtil.release(msg);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 出現異常就關閉cause.printStackTrace();ctx.close();}}

總結

以上是生活随笔為你收集整理的问道Netty。持续更新。。。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。