(轉)開源專案t-io
阿新 • • 發佈:2018-11-07
石墨文件:https://shimo.im/docs/tHwJJcvKl2AIiCZD/
(二期)18、開源t-io專案解讀
t-io:
websocket
- 同步
- 非同步
- 阻塞
- 非阻塞
- 一個連線一個執行緒
- 一個請求一個執行緒
**
Java對BIO、NIO、AIO的支援:
BIO、NIO、AIO適用場景分析:
- ChannelContext(通道上下文)
- GroupContext(服務配置與維護)
- AioHandler(訊息處理介面)
- AioListener(通道監聽者)
- Packet(應用層資料包)
- ObjWithLock(自帶讀寫鎖的物件)
t-io是基於tcp層協議的一個網路框架,所以在應用層與tcp傳輸層之間設計到一個數據的編碼與解碼問題,t-io讓我們能自定義資料協議,所以需要我們自己手動去編碼解碼過程。
https://gitee.com/tywo45/tio-showcase
- 匯入核心包
<dependency>
<groupId>org.t-io</groupId>
<artifactId>tio-core</artifactId>
</dependency>
- HelloServerStarter
- HelloServerAioHandler
- HelloPacket
- Const
- HelloClientStarter
- HelloClientAioHandler
- idea請安裝PlantUML intergration外掛
(初始化伺服器)
(客戶端與服務端通訊流程)
https://gitee.com/tywo45/tio-showcase
LoginReqBody loginReqBody = new LoginReqBody();
loginReqBody.setLoginname(loginname);
loginReqBody.setPassword(password);
ShowcasePacket reqPacket = new ShowcasePacket();
#這裡指定訊息型別
reqPacket.setType(Type.LOGIN_REQ);
reqPacket.setBody(Json.toJson(loginReqBody).getBytes(ShowcasePacket.CHARSET));
Tio.send(clientChannelContext, reqPacket);
- LoginReqBody
- ShowcasePacket
- clientChannelContext
ShowcasePacket showcasePacket = (ShowcasePacket) packet;
#獲取訊息型別
Byte type = showcasePacket.getType();
#根據訊息型別找到對應的訊息處理類
AbsShowcaseBsHandler<?> showcaseBsHandler = handlerMap.get(type);
if (showcaseBsHandler == null) {
log.error("{}, 找不到處理類,type:{}", channelContext, type);
return;
}
#執行訊息處理。訊息處理類必須繼承AbsShowcaseBsHandler
showcaseBsHandler.handler(showcasePacket, channelContext);
- handlerMap
- AbsShowcaseBsHandler
private static Map<Byte, AbsShowcaseBsHandler<?>> handlerMap = new HashMap<>();
static {
#把訊息型別與訊息處理類對映起來
handlerMap.put(Type.GROUP_MSG_REQ, new GroupMsgReqHandler());
handlerMap.put(Type.HEART_BEAT_REQ, new HeartbeatReqHandler());
handlerMap.put(Type.JOIN_GROUP_REQ, new JoinGroupReqHandler());
handlerMap.put(Type.LOGIN_REQ, new LoginReqHandler());
handlerMap.put(Type.P2P_REQ, new P2PReqHandler());
}
log.info("收到點對點請求訊息:{}", Json.toJson(bsBody));
ShowcaseSessionContext showcaseSessionContext = (ShowcaseSessionContext) channelContext.getAttribute();
P2PRespBody p2pRespBody = new P2PRespBody();
p2pRespBody.setFromUserid(showcaseSessionContext.getUserid());
p2pRespBody.setText(bsBody.getText());
ShowcasePacket respPacket = new ShowcasePacket();
respPacket.setType(Type.P2P_RESP);
respPacket.setBody(Json.toJson(p2pRespBody).getBytes(ShowcasePacket.CHARSET));
Tio.sendToUser(channelContext.groupContext, bsBody.getToUserid(), respPacket);
專案整合:
<dependency>
<groupId>org.t-io</groupId>
<artifactId>tio-websocket-server</artifactId>
<version>0.0.5-tio-websocket</version>
</dependency>
程式碼結構
事件定義
new Object() {
@Subscribe
public void lister(Integer integer) {
System.out.printf("%d from int%n", integer);
}
}
事件釋出
//定義事件
final EventBus eventBus = new EventBus();
//註冊事件
eventBus.register(new Object() {
//使用@Subscribe說明訂閱事件處理方法
@Subscribe
public void lister(Integer integer) {
System.out.printf("%s from int%n", integer);
}
@Subscribe
public void lister(Number integer) {
System.out.printf("%s from Number%n", integer);
}
@Subscribe
public void lister(Long integer) {
System.out.printf("%s from long%n", integer);
}
});
//釋出事件
eventBus.post(1);
eventBus.post(1L);
專案的而運用
主要處理事件
關鍵類:
呼叫:
邏輯:
/**
* 新增好友成功之後向對方推送訊息
* */
public static void pushAddFriendMessage(long applyid){
if(applyid==0){
return;
}
Apply apply = applyService.getApply(applyid);
ChannelContext channelContext = getChannelContext(""+apply.getUid());
//先判斷是否線上,再去查詢資料庫,減少查詢次數
if (channelContext != null && !channelContext.isClosed()) {
LayimToClientAddFriendMsgBody body = new LayimToClientAddFriendMsgBody();
User user = getUserService().getUser(apply.getToid());
if (user==null){return;}