Netty实战 IM即时通讯系统(二)Netty简介
##
Netty實戰 IM即時通訊系統(二)Netty簡介零、 目錄
- Netty 簡介
- Netty 環境配置
- 服務端啟動流程
- 實戰: 客戶端和服務端雙向通信
- 數據傳輸載體ByteBuf介紹
- 客戶端與服務端通信協議編解碼
- 實現客戶端登錄
- 實現客戶端與服務端收發消息
- pipeline與channelHandler
- 構建客戶端與服務端pipeline
- 拆包粘包理論與解決方案
- channelHandler的生命周期
- 使用channelHandler的熱插拔實現客戶端身份校驗
- 客戶端互聊原理與實現
- 群聊的發起與通知
- 群聊的成員管理(加入與退出,獲取成員列表)
- 群聊消息的收發及Netty性能優化
- 心跳與空閑檢測
- 總結
- 擴展
二、 Netty簡介
場景: 客戶端每隔兩秒發送一個帶有時間戳的“hello world”給服務端 , 服務端收到之后打印。
代碼:
IOServer.java/*** @author 閃電俠*/public class IOServer {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8000);// (1) 接收新連接線程new Thread(() -> {while (true) {try {// (1) 阻塞方法獲取新的連接Socket socket = serverSocket.accept();// (2) 每一個新的連接都創建一個線程,負責讀取數據new Thread(() -> {try {int len;byte[] data = new byte[1024];InputStream inputStream = socket.getInputStream();// (3) 按字節流方式讀取數據while ((len = inputStream.read(data)) != -1) {System.out.println(new String(data, 0, len));}} catch (IOException e) {}}).start();} catch (IOException e) {}}}).start();}}IOClient.java/*** @author 閃電俠*/public class IOClient {public static void main(String[] args) {new Thread(() -> {try {Socket socket = new Socket("127.0.0.1", 8000);while (true) {try {socket.getOutputStream().write((new Date() + ": hello world").getBytes());Thread.sleep(2000);} catch (Exception e) {}}} catch (IOException e) {}}).start();}}IO編程,模型在客戶端較少的場景下運行良好 , 但是客戶端比較多的業務來說 , 單機服務端可能需要支撐成千上萬的連接, IO模型可能就不太合適了 , 原因:
為了解決這些問題 , JDK1.4之后提出了NIO
NIO 是如何解決一下三個問題。
原生NIO 實現
/*** 服務端* */ class NIO_server_test_01{public static void start () throws IOException {Selector serverSelect = Selector.open();Selector clientSelect = Selector.open();new Thread(() -> {try {ServerSocketChannel socketChannel = ServerSocketChannel.open();socketChannel.socket().bind(new InetSocketAddress(8000)); // 監聽端口socketChannel.configureBlocking(false); // 是否阻塞socketChannel.register(serverSelect, SelectionKey.OP_ACCEPT);while ( true ) {// 檢測是否有新的連接if(serverSelect.select(1) > 0) { // 1 是超時時間 select 方法返回當前連接數量Set<SelectionKey> set = serverSelect.selectedKeys();set.stream().filter(key -> key.isAcceptable()).collect(Collectors.toList()).forEach(key ->{try {// 每次來一個新的連接, 不需要創建新的線程 , 而是注冊到clientSelectorSocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();clientChannel.configureBlocking(false);clientChannel.register(serverSelect, SelectionKey.OP_ACCEPT);}catch(Exception e) {e.printStackTrace();}finally {set.iterator().remove();}});}}}catch (Exception e) {e.printStackTrace();}}).start();new Thread(() -> {try {// 批量輪詢 有哪些連接有數據可讀while ( true ) {if(clientSelect.select(1) > 0) {clientSelect.selectedKeys().stream().filter(key -> key.isReadable()).collect(Collectors.toList()).forEach(key -> {try {SocketChannel clientChannl = (SocketChannel) key.channel();ByteBuffer bf = ByteBuffer.allocate(1024);// 面向byteBufferclientChannl.read(bf);bf.flip();System.out.println(Charset.defaultCharset().newDecoder().decode(bf).toString());}catch ( Exception e) {e.printStackTrace();}finally {clientSelect.selectedKeys().iterator().remove();key.interestOps(SelectionKey.OP_READ);}});}}}catch (Exception e) {e.printStackTrace();}}).start();}}原生NIO 進行網絡開發的缺點:
JDK 的NIO 猶如帶刺的玫瑰 , 雖然美好 , 讓人向往 , 但是使用不當會讓你抓耳撓腮 , 痛不欲生 , 正因為如此 , Netty橫空出世!(作者這才華 嘖嘖嘖~)
maven 依賴
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.6.Final</version> </dependency>NettyServer
/*** @author outman* */class Netty_server_02 {public void start () {ServerBootstrap serverBootstrap = new ServerBootstrap();NioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup woker = new NioEventLoopGroup();serverBootstrap.group(boss ,woker).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {@Overrideprotected void channelRead0(ChannelHandlerContext cxt, String msg) throws Exception {System.out.println(msg);}});}}).bind(8000);}}NettyClient
/**
* @author outman
* */
class Netty_client_02 {
}
在客戶端程序中 , group 對應了我們IOClient 中 新起的線程。
剩下的邏輯 我們在后文中詳細分析 , 現在你可以把 Netty_server_02 和Netty_client_02 復制到 你的IDE 中 運行起來 感受世界 的美好 (注意 先啟動 服務端 再啟動客戶端 )
使用Netty 之后 整個世界都美好了, 一方面 Netty 對NIO 封裝的如此完美 , 另一方面 , 使用Netty 之后 , 網絡通信這塊的性能問題幾乎不用操心 , 盡情的讓Netty 榨干你的CPU 吧~~
總結
以上是生活随笔為你收集整理的Netty实战 IM即时通讯系统(二)Netty简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebDriver自动化测试框架详解
- 下一篇: Netty实战 IM即时通讯系统(三)N