Netty實戰(1)使用Netty搭建一個簡單的客戶端與伺服器的互動Demo
Netty 是一個基於 JAVA NIO 類庫的非同步通訊框架,它的架構特點是:非同步非阻塞、基於事件驅動、高效能、高可靠性和高可定製性。換句話說,Netty是一個NIO框架,使用它可以簡單快速地開發網路應用程式,比如客戶端和服務端的協議。Netty大大簡化了網路程式的開發過程比如TCP和UDP的 Socket的開發。Netty 已逐漸成為 Java NIO 程式設計的首選框架。
一. Netty 的優點:
- API 使用簡單,開發門檻低;
- 功能強大,預置了多種編解碼功能,支援多種主流協議;
- 定製能力強,可以通過 ChannelHandler 對通訊框架進行靈活的擴充套件;
- 效能高,通過與其它業界主流的 NIO 框架對比,Netty 的綜合性能最優;
- 社群活躍,版本迭代週期短,發現的 BUG 可以被及時修復,同時,更多的新功能會被加入;
- 經歷了大規模的商業應用考驗,質量得到驗證。在網際網路、大資料、網路遊戲、企業應用、電信軟體等眾多行業得到成功商用,證明了它完全滿足不同行業的商用標準。
二、搭建Netty的一個簡單應用
(1)新增Maven依賴 pom.xml檔案 主要是新增netty的依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.netty</groupId> <artifactId>telnetDemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.0.36.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
(2)SimpleServer(服務端)
package com; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * * Netty中,通訊的雙方建立連線後,會把資料按照ByteBuf的方式進行傳輸, * 例如http協議中,就是通過HttpRequestDecoder對ByteBuf資料流進行處理,轉換成http的物件。 * */ public class SimpleServer { private int port; public SimpleServer(int port) { this.port = port; } public void run() throws Exception { //EventLoopGroup是用來處理IO操作的多執行緒事件迴圈器 //bossGroup 用來接收進來的連線 EventLoopGroup bossGroup = new NioEventLoopGroup(); //workerGroup 用來處理已經被接收的連線 EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //啟動 NIO 服務的輔助啟動類 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) //配置 Channel .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 註冊handler ch.pipeline().addLast(new SimpleServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 繫結埠,開始接收進來的連線 ChannelFuture f = b.bind(port).sync(); // 等待伺服器 socket 關閉 。 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new SimpleServer(9999).run(); } }
(3)SimpleServerHandler(服務端請求處理Handler)
package com;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class SimpleServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("SimpleServerHandler.channelRead");
ByteBuf result = (ByteBuf) msg;
byte[] result1 = new byte[result.readableBytes()];
// msg中儲存的是ByteBuf型別的資料,把資料讀取到byte[]中
result.readBytes(result1);
String resultStr = new String(result1);
// 接收並列印客戶端的資訊
System.out.println("Client said:" + resultStr);
// 釋放資源,這行很關鍵
result.release();
// 向客戶端傳送訊息
String response = "hello client!";
// 在當前場景下,傳送的資料必須轉換成ByteBuf陣列
ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
encoded.writeBytes(response.getBytes());
ctx.write(encoded);
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 當出現異常就關閉連線
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
(4)SimpleClient(客戶端)
package com;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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 io.netty.channel.socket.nio.NioSocketChannel;
public class SimpleClient {
public void connect(String host, int port) throws Exception {
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new SimpleClientHandler());
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
SimpleClient client=new SimpleClient();
client.connect("127.0.0.1", 9999);
}
}
(5)SimpleClientHandler(客戶端請求處理Handler)
package com;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class SimpleClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("SimpleClientHandler.channelRead");
ByteBuf result = (ByteBuf) msg;
byte[] result1 = new byte[result.readableBytes()];
result.readBytes(result1);
System.out.println("Server said:" + new String(result1));
result.release();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 當出現異常就關閉連線
cause.printStackTrace();
ctx.close();
}
// 連線成功後,向server傳送訊息
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String msg = "hello Server!";
ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
encoded.writeBytes(msg.getBytes());
ctx.write(encoded);
ctx.flush();
}
}
相關推薦
python--DenyHttp項目(1)--socket編程:客戶端與服務器端
brush accept acc -- highlight 發送消息 src size 接受 查找了許多資料,實現了客戶端與服務器端的連接,通過虛擬機進行測試 服務器端IP:192.168.37.129 端口1122 客戶端IP: 192.168.37.1 端口1122
Mina學習(1):mina實現簡單服務端與客戶端
mina是一個基於javaNio網路通訊應用框架,使用mina可以輕鬆的搭建伺服器,接下來將使用mina搭建一個小型的服務端 原始碼–MinaServer.java package serv
Netty實戰(1)使用Netty搭建一個簡單的客戶端與伺服器的互動Demo
Netty 是一個基於 JAVA NIO 類庫的非同步通訊框架,它的架構特點是:非同步非阻塞、基於事件驅動、高效能、高可靠性和高可定製性。換句話說,Netty是一個NIO框架,使用它可以簡單快速地開發網路應用程式,比如客戶端和服務端的協議。Netty大大簡化了網
(掃盲貼)如何搭建一個簡單的本地PHP伺服器-WAMP基礎指南
在除錯WEB應用程式時,我們都需要很多配置,LAMP,ASP,IIS等等。而在所有方式中,最簡單的莫過於WAMP了。 WAMP是Windows下的Apache+Mysql+PHP的縮寫。 通過這個伺服器我們可以完全傻瓜的在一般的Windows PC上面搭建起一個WEB伺服器
Netty學習(1):Channel的概念
1. Channel Channel是Netty的核心概念之一,它是Netty網路通訊的主體,由它負責同對端進行網路通訊、註冊和資料操作等功能。 1.1 工作原理 如上圖所示: 一旦使用者端連線成功,將新建一個channel同該使用者端進行繫結 channel從EventL
Netty入門(一)環境搭建及使用
一、專案建立 在 Eclipse 中右鍵,新建->專案->Maven->Maven Project->下一步->選擇 quickstart 下一步->設定如圖(引數自取) 點選完成。 專案會自動建立
深度學習之PyTorch實戰(1)——基礎學習及搭建環境
最近在學習PyTorch框架,買了一本《深度學習之PyTorch實戰計算機視覺》,從學習開始,小編會整理學習筆記,並部落格記錄,希望自己好好學完這本書,最後能熟練應用此框架。 PyTorch是美國網際網路巨頭Facebook在深度學習框架Torch的基礎上使用Python重寫的一個全新的深度學習框架,
Scala學習筆記(9)—— Scala實戰專案(1)- 環境搭建
1 專案需求 1.1 資料庫管理(java實現) default my-db1 my-db2 id:資料庫編號 name : 資料庫名稱 location : 資料庫存放在 HDFS/S3/OSS 等檔案系統上的目錄 /user/hive/warehouse /user/
Netty學習總結(1)——Netty入門介紹
1.Netty是什麼? Netty是一個基於JAVA NIO類庫的非同步通訊框架,它的架構特點是:非同步非阻塞、基於事件驅動、高效能、高可靠性和高可定製性。 2.使用Netty能夠做什麼?
webpack3實戰(1)打包一個CDN引入的jQuery專案
前注: 如果可以,請給本專案加【Star】和【Fork】持續關注。 有疑義請點選這裡,發【Issues】。 1、需求列表 1、在html檔案裡,通過CDN引入了jQuery; 2、步驟 安裝依賴 npm install html檔案中引入
Hadoop實戰(1)_阿里雲搭建Hadoop2.x的偽分散式環境
環境:阿里雲伺服器 CentOS 7 x86_64 安裝介質:jdk-7u75-linux-i586.tar.gz,hadoop-2.4.1.tar.gz 安裝jdk tar -zxvf jdk-7u75-linux-i586.tar.gz 配置
Docker 實戰(1)- 使用 Jenkins 映象建立容器,並搭建 Python + Pytest +Allure 的自動化測試環境
如果你還想從頭學起 Docker,可以看看這個系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 安裝 Docker 直接參考我這篇文章哦:https://www.cnblogs.com/poloyy/p/13921450.h
ceph分布式存儲實戰(1)——ceph集群測試主機規劃
monit dep release host eas rst 存儲 實戰 hostname 主機規劃節點磁盤(4塊)網卡(2塊)mem/cpuOSHostName節點1os-ceph-node1/10G私Eth0:dhcp1G/1CentOS Linux release
Spring實戰(1)
手動 之前 ava singleton 標簽 測試 之間 解決 業務邏輯 本博客是參考Spring實戰第四版,對其中重要的知識點進行總結。 Spring是如何簡化java開發的? 答:(1)基於POJO的輕量級和最小侵入性編程;(2)通過依賴註入和面向接口來松耦合;
python+selenium(1)--環境搭建
重新 一個 輸入 3.x 成了 ade pytho 復習 安裝 做自動化也很長時間了,這段時間項目初期沒什麽事情幹就在復習以前做過的seleniu+python的知識,現在想做一個簡單的記錄,也對自己學習有一個驅動作用吧。 以上。 一、python下載地址: https
靈活強大的MySQL代理中間件ProxySQL應用實戰(1)
sys www 流量 均可 rpm -ivh 硬盤 代理 發的 table 一、常見的Mysql中間件介紹 很多人都會把中間件認為是讀寫分離,其實讀寫分離只是中間件可以提供的一種功能,最主要的功能還是在於他可以分庫分表。下面介紹下常見的開源mysql中間件。 DBProx
ServiceComb實戰 (1)org.springframework.web.HttpMediaTypeNotSupportedException
一、異常現象: @Override @PostMapping(path = "logon") public ResponseEntity<Boolean> logon(@RequestBody UserDTO user) { if (validateUs
大資料實戰(上)——環境搭建
設定 hostname 為hadoop: $hostname hadoop 設定ip地址與hostname關聯:$vim /etc/hosts 新增 IP地址 hadoop 關閉 iptables: $service iptabl
springboot實戰(1)springboot基本配置
1 入口類和@SpringBootApplication package com.wuk.springbootHello; import org.springframework.boot.SpringApplication; import org.springframework.b
ROS串列埠通訊(1)環境搭建
ROS串列埠通訊(1)環境搭建 引言 1、ubuntu串列埠驅動安裝和使用 1.1 安裝 1.2 使用 1.3 Ubuntu 檢視串列埠,設定串列埠許可權 2、Ubuntu下的串列埠助手cute