前言:
計划從這篇文章開始,【Hello World系列】分類下的文章都采取【三問+文檔+Demo】的形式介紹新技術。
為什么要用這樣的思路呢?因為,我覺得,很多時候,技術其實就是一個工具。可以想象個這樣的場景:
別人把一個斧頭樣的物品遞到你手上,接着什么話都不說,那么一臉蒙蔽的你肯定心里是有很多問題想問的。
首先,你可能會問【這是什么?】,先確定物品名,即【是什么】,對方可能回答【斧頭】
接着,你會問【拿來干嘛的?】,了解用途,即【有什么用】,可能回答【砍東西】
再接着,你會問【什么時候會用到?】,知道什么時候可以拿出來使用,即【使用場景】,可能回答【可以拿來砍樹】
*以下兩點是建立在 假設你對砍樹相關的專業知識不太了解 的基礎上
然后,你可能會說【砍樹的話,應該還有別的工具可以做到吧?】,即【可替代品】,可能回答【鋸子也可以做到】
再然后,你就會想知道【那為什么選擇用斧頭砍樹而不用鋸子呢?】,即【優缺點】,可能回答【斧頭的制作更簡單,但是用鋸子更省力】
初步了解后,就需要找一個遇到問題時可以參考的【說明書】,即【文檔】
另外,如果有人可以親自示范一下用法作為參考的【例子】就更好了,即【Demo】
這是一個比較適合我的思維方式,也很適合作為這個Hello World系列文章的大綱,希望能夠堅持下去。
好了,以下是正文。
【三問之一:是什么】
一個可以實現web socket通訊的java框架
【三問之二:有什么用】
目前我只用來實現基礎的web socket通訊
【三問之三:使用場景】
需要客戶端和服務器端之間互相發送即時消息的時候,比如即時網絡對戰的游戲
【三問之四:可替代品】
目前沒有發現可以實現web socket通訊的、比這個更好的java框架
【三問之五:優缺點】
優點:上手快,使用簡單;缺點:待發現。
【文檔】
https://smartboot.gitee.io/book/
【Demo】
項目結構
StringProtocol.java
package org.mandy.demo.hello_smart_socket; import java.nio.ByteBuffer; import org.smartboot.socket.Protocol; import org.smartboot.socket.transport.AioSession; public class StringProtocol implements Protocol<String> { @Override public String decode(ByteBuffer readBuffer, AioSession<String> session) { // |消息頭 | 消息體 | // | 6 | S | O | C | K | E | T | // 標志當前readBuffer的position位置 readBuffer.mark(); // 獲取消息頭內容,此時position會+1 byte length = readBuffer.get(); // 如果消息頭記錄的長度不等於消息體長度,則返回null,position不動 if (length != readBuffer.remaining()) { return null; } // 按照消息體長度創建byte數組 byte[] b = new byte[length]; // 讀取消息體內容放入byte數組 readBuffer.get(b); // 更新標志位 readBuffer.mark(); // 返回字符串 return new String(b); } }
Server.java
package org.mandy.demo.hello_smart_socket; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.smartboot.socket.MessageProcessor; import org.smartboot.socket.StateMachineEnum; import org.smartboot.socket.transport.AioQuickServer; import org.smartboot.socket.transport.AioSession; public class Server { static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws IOException { // 構造服務端對象 AioQuickServer<String> server = new AioQuickServer<String>(8999, new StringProtocol(), new MessageProcessor<String>() { // 對解析出來的消息進行處理 public void process(AioSession<String> session, String msg) { System.out.println("收到Client發來的消息[" + df.format(new Date()) + "]:" + msg); // 准備發給Client的內容 String rs = "Hi Client!"; // 內容轉成消息體的byte數組 byte[] rb = rs.getBytes(); // 創建消息頭的byte數組 byte[] head = {(byte) rb.length}; System.out.println("向Client發送消息[" + df.format(new Date()) + "]:" + new String(rb)); try { // 傳送消息頭 session.writeBuffer().write(head); // 傳送消息體 session.writeBuffer().write(rb); } catch (IOException e) { e.printStackTrace(); } } // 當枚舉事件發生時由框架觸發該方法 public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) { //System.out.println(stateMachineEnum); } }); // 啟動服務端 server.start(); } }
Client.java
package org.mandy.demo.hello_smart_socket; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ExecutionException; import org.smartboot.socket.MessageProcessor; import org.smartboot.socket.StateMachineEnum; import org.smartboot.socket.transport.AioQuickClient; import org.smartboot.socket.transport.AioSession; public class Client { static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException, ExecutionException, IOException { // 構造客戶端對象 AioQuickClient<String> client = new AioQuickClient<String>("127.0.0.1", 8999, new StringProtocol(), new MessageProcessor<String>() { public void process(AioSession<String> session, String msg) { System.out.println("收到Server發來的消息[" + df.format(new Date()) + "]:" + msg); } public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) { //System.out.println(stateMachineEnum); } }); // 啟動客戶端 AioSession<String> session = client.start(); // 准備發給Client的內容 String ss = "Hello Server!"; byte[] sb = ss.getBytes(); byte[] head = {(byte) sb .length}; System.out.println("向Server發送消息[" + df.format(new Date()) + "]:" + new String(sb)); try { session.writeBuffer().write(head); session.writeBuffer().write(sb); // 沖刷出流 session.writeBuffer().flush(); } catch (IOException e) { e.printStackTrace(); } } }
pom.xml
<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>org.mandy.demo</groupId> <artifactId>hello-smart-socket</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>hello-smart-socket</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.smartboot.socket</groupId> <artifactId>aio-core</artifactId> <version>1.4.2</version> </dependency> </dependencies> </project>
運行效果