1、作者本人是一個碼農,比較喜歡研究技術,特別是網路通訊。
2、JDK1.7升級了NIO類庫,升級后的NIO類庫被稱為NIO 2.0。正式提供了非同步文件I/O操作,同時提供了與UNIX網路編程事件驅動I/O對應的AIO。AIO的發布使得實現一套網路通訊框架變得相對簡單。但如果你不努力,可能也無法理解哦。
3、本人對netty比較喜歡,無論是其性能還是編程思想(JBOSS提供的一個java開源網路框架,可以說是java網路通訊里的一哥,極其穩定和強大的性能使得被廣泛使用)
4、有了netty為何還要自己造輪子?這裡有兩個原因,其一是本人就喜歡造輪子,這是病,改不了。其二,netty經過多年的發展,其生態體系已經比較龐大,導致其代碼比較臃腫,再者其高深的設計哲學我等凡夫俗子很難悟其精髓。因而索性自己造一個。
5、netty畢竟是別人的東西,還是老外的。並且國內也有許多優秀的開源框架。想了想,為何不自己搞一個呢,於是乎腦袋發熱,抽時間造了一個。
1、完全基於java aio,整個工程只依賴 slf4j(一個日誌的門面框架),對工程幾乎沒有入侵性。
2、借鑒了netty和其他框架的部分優秀設計思想,如責任鏈、內存池化、零拷貝等優秀的設計模式。
3、簡潔的代碼,清晰的註釋,以及提供了直接可用的多個插件,只要用過netty,那麼學習成本基本為零。
4、可直接在安卓上使用,服務與客戶端使用幾乎一致(api 26+或android 8.0+)
硬體條件:cpu:i7-7700 | 內存:16G | 網路:區域網 | 操作系統:win10家庭版 | jdk 8
經過本人簡單的測試,整體的性能和穩定性還是不錯的:
1、單連接發送一百萬條文本消息耗時277毫秒,這個性能總體上還過得去。
2、開啟了SSL以後發送一百萬條文本消息大概耗時3.8秒,這個性能也算樂觀,因為畢竟SSL本身對消息的加密和解密是非常消耗性能的。
3、同時開啟10條連接,每條連接發送一百萬條文本消息,每條連接平均耗時是比較均衡的,平均三百多毫秒。性能非常可觀
4、伺服器啟動時的內存消耗,啟動時內存消耗非常小,佔用還不到40m
5、連續發送一百萬條消息時的內存消耗,大概消耗160m左右,而且內存回收也非常迅速
先添加 slf4j 依賴:
//java 中使用org.slf4jslf4j-api
安卓中使用添加安卓版本:
// https://mvnrepository.com/artifact/org.slf4j/slf4j-android implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.26'
1、伺服器端啟動:
AioServerStarter server = new AioServerStarter(5555); server.bossThreadNum(10).channelInitializer(new ChannelInitializer() { @Override public void initChannel(AioChannel channel) throws Exception { //初始化責任鏈 DefaultChannelPipeline defaultChannelPipeline = channel.getDefaultChannelPipeline(); //添加結束符處理器 defaultChannelPipeline.addLast(new DelimiterFrameDecoder(DelimiterFrameDecoder.lineDelimiter)); //添加string類型消息解碼器 defaultChannelPipeline.addLast(new StringDecoder()); //自定義的消息處理器 defaultChannelPipeline.addLast(new SimpleHandler()); } }); server.start();
//簡單的消息處理器 public class SimpleHandler extends SimpleChannelInboundHandler{ @Override public void channelAdded(AioChannel aioChannel) { System.out.println("連接過來了"); } @Override public void channelClosed(AioChannel aioChannel) { System.out.println("連接關閉了"); } @Override public void channelRead0(AioChannel aioChannel, String str) { System.out.println("讀取消息:" +str); try { byte[] msgBody = (str + "\r\n").getBytes("utf-8"); //返回消息給客戶端 aioChannel.writeAndFlush(msgBody); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } @Override public void exceptionCaught(AioChannel aioChannel, Throwable cause, PipelineDirection pipelineDirection) { System.out.println("出錯了"); } }
2、客戶端啟動:
AioClientStarter client = new AioClientStarter("127.0.0.1", port); client.channelInitializer(new ChannelInitializer() { @Override public void initChannel(AioChannel channel) throws Exception { //責任鏈 DefaultChannelPipeline defaultChannelPipeline = channel.getDefaultChannelPipeline(); //字元串編碼器 defaultChannelPipeline.addLast(new StringEncoder()); //指定結束符解碼器 defaultChannelPipeline.addLast(new DelimiterFrameDecoder(DelimiterFrameDecoder.lineDelimiter)); //字元串解碼器 defaultChannelPipeline.addLast(new StringDecoder()); //定義消息解碼器 defaultChannelPipeline.addLast(new SimpleHandler()); } }); try { client.start(); Thread.sleep(1000); //獲取通道 AioChannel aioChannel = client.getAioChannel(); //發送消息 String s = "me\r\n"; byte[] msgBody = s.getBytes("utf-8"); aioChannel.writeAndFlush(msgBody); } catch (Exception e) { e.printStackTrace(); }
最簡單的使用方式就完成了。
更多詳情可以查看碼云:https://gitee.com/kokjuis/getty
[admin
]