此係列文章來源於總結歸納Netty 入門與實戰:仿寫微信 IM 即時通訊系統
代碼:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.AttributeKey;
public class NettyServer {
private static final int BEGIN_PORT = 8000;
public static void main(String[] args) {
NioEventLoopGroup boosGroup = new NioEventLoopGroup(); //創建新連接
NioEventLoopGroup workerGroup = new NioEventLoopGroup(); //讀取數據以及業務邏輯處理
final ServerBootstrap serverBootstrap = new ServerBootstrap(); //引導類,進行服務端的啓動工作
final AttributeKey<Object> clientKey = AttributeKey.newInstance("clientKey");
serverBootstrap
.group(boosGroup, workerGroup) //給引導類配置兩大線程組(線程模型)
.channel(NioServerSocketChannel.class) //指定IO模型爲NIO
.attr(AttributeKey.newInstance("serverName"), "nettyServer") //給NioServerSocketChannel指定一些自定義屬性,通過channel.attr()取出這個屬性
.childAttr(clientKey, "clientValue") //給每一條連接指定自定義屬性
.option(ChannelOption.SO_BACKLOG, 1024)//表示系統用於臨時存放已完成三次握手的請求的隊列的最大長度
.childOption(ChannelOption.SO_KEEPALIVE, true)//是否開啓TCP底層心跳機制,true爲開啓
.childOption(ChannelOption.TCP_NODELAY, true)//是否開啓Nagle算法,true表示關閉,false表示開啓,通俗地說,如果要求高實時性,有數據發送時就馬上發送,就關閉,如果需要減少發送次數減少網絡交互,就開啓。
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel ch) {
System.out.println(ch.attr(clientKey).get());
}
}); //定義後續每條連接的數據讀寫,業務處理邏輯
bind(serverBootstrap, BEGIN_PORT); //遞增綁定端口
}
private static void bind(final ServerBootstrap serverBootstrap, final int port) {
serverBootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println("端口[" + port + "]綁定成功!");
} else {
System.err.println("端口[" + port + "]綁定失敗!");
bind(serverBootstrap, port + 1);
}
});
}
}
解析:
*首先創建了兩個NioEventLoopGroup
,這兩個對象可以看做是傳統IO編程模型的兩大線程組,bossGroup
表示監聽端口,accept 新連接的線程組,workerGroup
表示處理每一條連接的數據讀寫的線程組。類比爲:一個工廠要運作,必然要有一個老闆負責從外面接活,然後有很多員工,負責具體幹活,老闆就是bossGroup
,員工們就是workerGroup
,bossGroup
接收完連接,扔給workerGroup
去處理。
*然後創建了一個引導類 ServerBootstrap的對象
,這個類將引導我們進行服務端的啓動工作
*通過.group(bossGroup, workerGroup)
給引導類配置兩大線程組,指定引導類的線程模型
*通過.channel(NioServerSocketChannel.class)
來指定 IO 模型
*調用childHandler()
方法,給這個引導類創建一個ChannelInitializer
,定義後續每條連接的數據讀寫,業務處理邏輯
*ChannelInitializer
這個類中,NioSocketChannel
就是 Netty 對 NIO 類型的連接的抽象,前面NioServerSocketChannel
也是對 NIO 類型的連接的抽象
*遞增地綁定端口,起始端口號BEGIN_PORT=8000,若綁定失敗則端口號+1,直到綁定端口成功
總結:
1、創建一個引導類,然後給他指定線程模型,IO模型,連接讀寫處理邏輯,綁定端口之後,服務端就啓動起來了。
2、bind 方法是異步的,我們可以通過這個異步機制來實現端口遞增綁定。
3、Netty 服務端啓動額外的參數,主要包括給服務端 Channel 或者客戶端 Channel 設置屬性值,設置底層 TCP 參數。