Netty实战 IM即时通讯系统(四)服务端启动流程
##
Netty實戰 IM即時通訊系統(四)服務端啟動流程零、 目錄
- Netty 簡介
- Netty 環境配置
- 服務端啟動流程
- 實戰: 客戶端和服務端雙向通信
- 數據傳輸載體ByteBuf介紹
- 客戶端與服務端通信協議編解碼
- 實現客戶端登錄
- 實現客戶端與服務端收發消息
- pipeline與channelHandler
- 構建客戶端與服務端pipeline
- 拆包粘包理論與解決方案
- channelHandler的生命周期
- 使用channelHandler的熱插拔實現客戶端身份校驗
- 客戶端互聊原理與實現
- 群聊的發起與通知
- 群聊的成員管理(加入與退出,獲取成員列表)
- 群聊消息的收發及Netty性能優化
- 心跳與空閑檢測
- 總結
- 擴展
###四、 服務端啟動流程
服務端Demo
public class NettyServer {public static void main(String[] args) {NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);NioEventLoopGroup workerGroup = new NioEventLoopGroup();ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {protected void initChannel(NioSocketChannel ch) {}});serverBootstrap.bind(8000);}}到這里我們最小化參數配置就完成了 , 總結一下 , 想要啟動一個Netty服務端 , 我們需要指定三個類屬性:線程模型、 IO模型、處理邏輯 , 有了這三者之后再調用 bind(8000) , 我們就可以在本地綁定一個8000端口啟動起來 。
自動綁定遞增端口
在上面代碼中我們直接綁定了8000端口 , 接下來我們實現一個稍微復雜的邏輯: 我們指定一個起始端口 , 比如:1000 , 然后判斷是否綁定成功 , 如果不成功就 綁定1001 , 直到成功為止。
serverBootStrap.bind() 這個方法時異步的 , 調用之后立即返回結果 , 但是并不知道是否綁定成功, 他的返回值是一個ChannelFuture , 我們可以給這個ChannelFuture 添加一個監聽器 GenericFutureListener , 然后我們在GenericFutureListener 的operationComplete 方法里面 , 我們可以監聽到端口是否綁定成功 , 接下來是檢測端口是否綁定成功的代碼:
/**
-
自動遞增綁定有效端口
-
@author outman
-
*/
private static void bind(ServerBootstrap serverBootstrap, int port) {serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {
@Overridepublic void operationComplete(Future<? super Void> future) throws Exception {if(future.isSuccess()) {System.out.println("成功綁定端口:"+port);}else {System.out.println("綁定端口失敗:"+ port);bind(serverBootstrap, port+1);}}});
}
執行結果: (我的mysql 占用了3306端口 , 所以3306綁定失敗)
綁定端口失敗:3306
成功綁定端口:3307
服務端啟動相關的其他方法
handler(): handler() 方法可以和之前分析的childHandler() 對應起來 ,childHandler() 用于指定處理新連接數據的業務邏輯 , handler用于指定服務端啟動過程中的一些邏輯
serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() {@Overrideprotected void initChannel(NioServerSocketChannel ch) throws Exception {System.out.println("服務端啟動中..."); }});attr(): attr()方法可以給服務端的channel , 也就是NioServerSocketChannel指定一些自定義屬性 , 然后我們可以通過channel.attr()取出這個屬性 , 比如 , 我們可以給服務端channel指定一個serverName 屬性 , 屬性值NettyServer , 其實說白了就是給NioServerSocketChannel維護了一個map:
//設置服務端屬性serverBootstrap.attr(AttributeKey.newInstance("serverName"), "NettyServer");serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() {@Overrideprotected void initChannel(NioServerSocketChannel channel) throws Exception {// 取出服務端屬性Attribute<Object> serverName = channel.attr(AttributeKey.valueOf("serverName") );System.out.println( serverName.get()+"服務端啟動中..."); }});childAttr() : 可以通過childAttr 給每一條連接設置自定義屬性
//給連接設置自定義屬性serverBootstrap.childAttr(AttributeKey.newInstance("clientName"), "NettyClient");serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel childChannel) throws Exception {// 取出連接中的自定義屬性childChannel.attr(AttributeKey.valueOf("clientName"));}});childOption(): childOption方法可以給每條連接設置一些TCP底層相關的屬性:
ChannelOption.SO_KEEPALIVE表示是否開啟TCP底層心跳機制,true為開啟
ChannelOption其他參數詳解: https://www.cnblogs.com/googlemeoften/p/6082785.html
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);serverBootstrap.childOption(ChannelOption.SO_BACKLOG, 10);option(): 給服務端channel 設置一些屬性:
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024)//表示系統用于存放已經完成三次握手的請求的隊列的最大長度 , 如果建立連接頻繁, 服務器處理創建新連接較慢, 可以適當調大這個參數。總結
疑問:
總結
以上是生活随笔為你收集整理的Netty实战 IM即时通讯系统(四)服务端启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty实战 IM即时通讯系统(三)N
- 下一篇: Netty实战 IM即时通讯系统(五)客