smart-socket是什麼
smart-socket文檔地址
http://smartsocket.mydoc.io/?t=260338
碼雲地址:
https://gitee.com/smartboot/smart-socket
smart(百度翻譯:聰明的;敏捷的;漂亮的;整齊的),從爲項目起名開始,便對其寄予了厚望。專注於通信組件的研究與發展,摒棄一切大而全的解決方案,僅提供小而美的基礎服務。無論您是從事IOT、IM、RPC,還是其餘通信領域的開發工作,相信smart-socket都是非常酷的選擇。如果要用一句話來爲smart-socket打call,那就是:遇見smart-socket,你就已經贏在起跑線了。
關於開源
JDK7雖然已經發布很長一段時間了,但開源社區對於其AIO的新特性貌似並不熱情。對於通信方面的技術訴求,似乎大家都習慣於Netty、Mina。“Stop Trying to Reinvent the Wheel”不要重複造輪子,幾乎每個程序員都被灌輸過這個概念,理所當然的沉浸在各自的舒適區,享受着開源社區提供的各項技術支撐。舉個跟本文相契合的例子,如果工作中遇到通信相關的需求,廣大Java程序員腦海裏首先想到的必然是Netty或Mina,即便從未接觸過Netty/Mina,但在心裏認定只有這兩個框架才能解決自己面臨的問題。這樣的現狀可能歸咎於現在我們太急躁,工作的壓力致使沒時間給自己充電,尤其是那種不常用且稍微有點深度的技術點,已經沒心力再去細細琢磨了。所幸還有一批好學的程序員在工作之餘做着一些看似平凡的事,踏踏實實專研這些技術點並作出一些小小的作品,同時爲開源社區注入新鮮血液。目前碼雲上已知的Java AIO項目有tio、Voovan、baseio以及本文的主角:smart-socket,這幾個作品還無任何一款能形成足夠的影響力被廣大Javaer認可,但通過開源的推廣與磨練,相信未來AIO的開源環境會比現在更加繁榮。
smart-socket立項之初便已嚴苛的要求進行開發,追求各方面都達到極致。首先,smart-socket是個非常輕量級的項目,只有依賴log4j2作爲項目的日誌組件。smart-socket發佈的jar包僅僅20KB,簡潔的接口設計可以非常方便的在業務中接入通信服務。不過我們更期望看到的是接觸到smart-socket的朋友可以將其作爲學習Java Socket編程的素材,如果smart-socket能在這方面給予您一絲幫助,那我便會絕對自己做了一件有意義的事。
官方指南假設您已瞭解ByteBuffer,並對Socket編程具備一定基礎。如果您剛開始接觸Socket,將smart-socket作爲您的第一步可能不是個好的決定。
Maven依賴
smart-socket已上傳至Maven倉庫,使用前需要向其引入您的項目工程中。
<!-- https://mvnrepository.com/artifact/org.smartboot.socket/aio-core -->
<dependency>
<groupId>org.smartboot.socket</groupId>
<artifactId>aio-core</artifactId>
<version>1.3.2</version>
</dependency>
通信開發
基於smart-socket進行通信服務的開發,主要有三個步驟:
- 協議編解碼
- 消息處理
- 啓動服務
接下來我們會通過一個簡單例子來演示如何通過smart-socket開發服務端與客戶端程序。爲簡化操作,服務端與客戶端交互的數據爲一個整型數據。
一、協議編解碼
正常情況下服務端與客戶端通信共用同一套協議規則,因此我們只需編寫一份協議編解碼實現即可。如下所示,協議編解碼的需要實現接口Protocol。
public class IntegerProtocol implements Protocol<Integer> {
private static final int INT_LENGTH = 4;
@Override
public Integer decode(ByteBuffer data, AioSession<Integer> session, boolean eof) {
if (data.remaining() < INT_LENGTH)
return null;
return data.getInt();
}
@Override
public ByteBuffer encode(Integer s, AioSession<Integer> session) {
ByteBuffer b = ByteBuffer.allocate(INT_LENGTH);
b.putInt(s);
b.flip();
return b;
}
}
上述代碼很簡單,一個整數的長度爲4byte,所以只要長度大於等於4,我們就能解析到一個整數。
二、消息處理
業務消息的處理需要實現接口MessageProcessor
,該接口只有兩個方法:process
,stateEvent
。其中 stateEvent用於定義AioSession狀態機的監控與處理。process則會處理每一個接收到的業務消息。
服務端
public class IntegerServerProcessor implements MessageProcessor<Integer> {
@Override
public void process(AioSession<Integer> session, Integer msg) {
Integer respMsg = msg + 1;
System.out.println("接受到客戶端數據:" + msg + " ,響應數據:" + (respMsg));
try {
session.write(respMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void stateEvent(AioSession<Integer> session, StateMachineEnum stateMachineEnum, Throwable throwable) {
}
}
客戶端
public class IntegerClientProcessor implements MessageProcessor<Integer> {
private AioSession<Integer> session;
@Override
public void process(AioSession<Integer> session, Integer msg) {
System.out.println("接受到服務端響應數據:" + msg);
}
@Override
public void stateEvent(AioSession<Integer> session, StateMachineEnum stateMachineEnum, Throwable throwable) {
switch (stateMachineEnum) {
case NEW_SESSION:
this.session = session;
break;
default:
System.out.println("other state:" + stateMachineEnum);
}
}
public AioSession<Integer> getSession() {
return session;
}
}
三、啓動服務
服務端
public class IntegerServer {
public static void main(String[] args) {
AioQuickServer server = new AioQuickServer()
.bind(8888)
.setProtocol(new IntegerProtocol())
.setProcessor(new IntegerServerProcessor());
try {
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客戶端
public class IntegerClient {
public static void main(String[] args) throws Exception {
IntegerClientProcessor processor=new IntegerClientProcessor();
AioQuickClient aioQuickClient=new AioQuickClient()
.connect("localhost",8888)
.setProtocol(new IntegerProtocol())
.setProcessor(processor);
aioQuickClient.start();
processor.getSession().write(1);
Thread.sleep(1000);
aioQuickClient.shutdown();
}
}