原文:https://my.oschina.net/u/2984386/blog/1630300

  • 背景介绍

t-io是一款国产开源的网络编程框架,主要是特点:简单,易上手,AIP封装通俗易懂,适合一般企业简易即时通讯工具开发。宣传性能也不错:百万TCP长连接,不过个人也没测试过,所以想试一试看看。本文档主要记录了简单群组聊天的实现,同时记录下学习t-io的过程。其实    http://t-io.org/#/ 中有比较完整的Demo,本文也主要是参考其中。

  • 服务端

启动类:

package com.dooper.server;

import org.tio.server.AioServer;
import org.tio.server.ServerGroupContext;
import org.tio.server.intf.ServerAioListener; import com.dooper.common.packet.Constant;
import com.dooper.server.handler.MyServerAioHandler; public class ServerStarter { public static MyServerAioHandler aioHandler = new MyServerAioHandler(); public static ServerAioListener aioListener = null; public static ServerGroupContext serverGroupContext = new ServerGroupContext(aioHandler, aioListener); public static AioServer aioServer = new AioServer(serverGroupContext); public static String serverIp = null; public static int serverPort = Constant.PORT; public static void main(String[] args) throws Exception{
serverGroupContext.setHeartbeatTimeout(Constant.TIMEOUT);
aioServer.start(serverIp, serverPort);
} }

消息处理

消息处理中有绑定组的步骤,实际不应该在此处,应该是有额外的处理类来处理群组绑定,此处因为懒,直接写在里面了。

package com.dooper.server.handler;

import java.nio.ByteBuffer;

import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.core.exception.AioDecodeException;
import org.tio.core.intf.Packet;
import org.tio.server.intf.ServerAioHandler; import com.dooper.common.packet.MyPacket; /**
* server
*
*
*/
public class MyServerAioHandler implements ServerAioHandler{ @Override
public Packet decode(ByteBuffer buffer, ChannelContext chanelContext) throws AioDecodeException {
int readableLength = buffer.limit() - buffer.position();
if(readableLength < MyPacket.HEADER_LENGHT){
return null;
} int bodyLength = buffer.getInt();
if(bodyLength<0){
throw new AioDecodeException("bodyLength ["+bodyLength+"] is not rigth,remote"+chanelContext.getClientNode());
}
int neededLength = MyPacket.HEADER_LENGHT+bodyLength;
int isDataEnough = readableLength - neededLength;
if(isDataEnough < 0){
return null;
}else{
MyPacket packet = new MyPacket();
if(bodyLength > 0){
byte[] dst = new byte[bodyLength];
buffer.get(dst);
packet.setBody(dst);
}
return packet;
}
} @Override
public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) {
MyPacket myPacket = (MyPacket)packet;
byte[] body = myPacket.getBody();
int bodyLen = 0;
if(body != null){
bodyLen = body.length;
} int allLen = MyPacket.HEADER_LENGHT + bodyLen;
ByteBuffer buffer = ByteBuffer.allocate(allLen);
buffer.order(groupContext.getByteOrder());
buffer.putInt(bodyLen); if(body != null){
buffer.put(body);
} return buffer;
} @Override
public void handler(Packet packet, ChannelContext channelContext) throws Exception {
MyPacket myPacket = (MyPacket)packet;
byte[] body = myPacket.getBody();
if(body != null){
String str = new String(body,MyPacket.CHARSET);
System.out.println("客户端发送的消息:"+str);
Aio.bindGroup(channelContext, "group1");
GroupHandler gh = new GroupHandler();
gh.handler(myPacket, channelContext); }
return; } }

自定义的群组消息处理

package com.dooper.server.handler;

import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.intf.Packet; import com.dooper.common.packet.MyPacket; public class GroupHandler extends MsgHandler{ @Override
public void handler(Packet packet, ChannelContext channelContext) throws Exception {
MyPacket myPacket = (MyPacket)packet;
byte[] body = myPacket.getBody();
if(body!=null){
MyPacket mp = new MyPacket();
System.out.println("服务端收到消息:"+new String(body,MyPacket.CHARSET));
mp.setBody((channelContext.getClientNode()+":"+new String(body,MyPacket.CHARSET)).getBytes(MyPacket.CHARSET));
Aio.sendToGroup(channelContext.getGroupContext(), "group1", mp);
}
} }
  • 客户端

启动类

package com.dooper.client;

import java.util.Scanner;

import org.tio.client.AioClient;
import org.tio.client.ClientChannelContext;
import org.tio.client.ClientGroupContext;
import org.tio.client.ReconnConf;
import org.tio.client.intf.ClientAioHandler;
import org.tio.client.intf.ClientAioListener;
import org.tio.core.Aio;
import org.tio.core.Node; import com.dooper.common.packet.Constant;
import com.dooper.common.packet.MyPacket; public class MyClientStarter { public static Node serverNode = new Node(Constant.SERVER,Constant.PORT); public static ClientAioHandler aioClientHandler = new MyClientAioHandler(); public static ClientAioListener aioListener = null; private static ReconnConf reconnConf = new ReconnConf(5000L); private static ClientGroupContext clientGroupContext = new ClientGroupContext(aioClientHandler, aioListener,reconnConf); public static AioClient aioClient = null; public static ClientChannelContext clientChannelContext = null; public static void main(String[] args) throws Exception{
clientGroupContext.setHeartbeatTimeout(Constant.TIMEOUT); aioClient = new AioClient(clientGroupContext); clientChannelContext = aioClient.connect(serverNode); Scanner sc = new Scanner(System.in);
System.out.println("请发送群组消息:");
String line = sc.nextLine(); // 这个就是用户输入的数据
while (true) {
if ("exit".equalsIgnoreCase(line)) {
System.out.println("Thanks for using! bye bye.");
break;
} else{
sendGroup(line);
}
line = sc.nextLine(); // 这个就是用户输入的数据
}
// send();
sc.close();
} public static void send() throws Exception{
MyPacket packet = new MyPacket(); packet.setBody("hello world".getBytes(MyPacket.CHARSET)); Aio.send(clientChannelContext, packet); } public static void sendGroup(String msg) throws Exception{
Aio.bindGroup(clientChannelContext, "group1");
MyPacket packet = new MyPacket();
packet.setBody(msg.getBytes(MyPacket.CHARSET));
Aio.sendToGroup(clientGroupContext, "group1", packet);
} }

消息处理类

package com.dooper.client;

import java.nio.ByteBuffer;

import org.tio.client.intf.ClientAioHandler;
import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.core.exception.AioDecodeException;
import org.tio.core.intf.Packet; import com.dooper.common.packet.MyPacket; public class MyClientAioHandler implements ClientAioHandler { private static MyPacket heartbeatPacket = new MyPacket(); /**
* ���룺
*/
@Override
public Packet decode(ByteBuffer buffer, ChannelContext channelContext) throws AioDecodeException {
int readableLength = buffer.limit() - buffer.position(); if(readableLength < MyPacket.HEADER_LENGHT){
return null;
} int bodyLength = buffer.getInt(); if(bodyLength < 0){
throw new AioDecodeException("bodyLength ["+bodyLength+"] is not right,remote:"+channelContext.getClientNode());
} int neededLength = MyPacket.HEADER_LENGHT + bodyLength; int isDataEnough = readableLength - neededLength; if(isDataEnough < 0){
return null;
}else{
MyPacket myPacket = new MyPacket(); if(bodyLength > 0){
byte[] dst = new byte[bodyLength];
buffer.get(dst);
myPacket.setBody(dst);
}
return myPacket;
} } /**
* ���룺
*/
@Override
public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) {
MyPacket myPacket = (MyPacket)packet; byte[] body = myPacket.getBody(); int bodyLen = 0; if(body != null){
bodyLen = body.length;
} int allLen = MyPacket.HEADER_LENGHT +bodyLen; ByteBuffer buffer = ByteBuffer.allocate(allLen); buffer.order(groupContext.getByteOrder()); buffer.putInt(bodyLen); if(body != null){
buffer.put(body);
} return buffer;
} @Override
public void handler(Packet packet, ChannelContext channelContext) throws Exception {
MyPacket myPacket = (MyPacket)packet;
byte[] body = myPacket.getBody();
if(body!=null){
String str = new String(body,MyPacket.CHARSET);
System.out.println(str); }
return ;
} @Override
public Packet heartbeatPacket() {
return heartbeatPacket;
} }

基于t-io的MI工具实现的更多相关文章

  1. 在线白板,基于socket.io的多人在线协作工具

    首发:个人博客,更新&纠错&回复 是昨天这篇博文留的尾巴,socket.io库的使用练习,成品地址在这里. 代码已经上传到github,传送门.可以开俩浏览器看效果. 现实意义是俩人在 ...

  2. Hive -- 基于Hadoop的数据仓库分析工具

    Hive是一个基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库 ...

  3. 基于Web的IIS管理工具

    Servant:基于Web的IIS管理工具   Servant for IIS是个管理IIS的简单.自动化的Web管理工具.安装Servant的过程很简单,只要双击批处理文件Install Serva ...

  4. 搭建基于MySQL的读写分离工具Amoeba

    搭建基于MySQL的读写分离工具Amoeba: Amoeba工具是实现MySQL数据库读写分离的一个工具,前提是基于MySQL主从复制来实现的: 实验环境(虚拟机): 主机 角色 10.10.10.2 ...

  5. ART模式下基于Xposed Hook开发脱壳工具

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78092365 Dalvik模式下的Android加固技术已经很成熟了,Dalvik ...

  6. Processon 一款基于HTML5的在线作图工具

    CSDN的蒋涛不久前在微博上评价说ProcessOn是web版的visio,出于好奇私下对ProcessOn进行了一番研究.最后发现无论是在用户体验上,还是在技术上,ProcessOn都比微软的Vis ...

  7. 基于数据库的自动化生成工具,自动生成JavaBean、自动生成数据库文档等(v4.1.2版)

            目录:            第1版:http://blog.csdn.net/vipbooks/article/details/51912143            第2版:htt ...

  8. 基于socket.io的实时在线选座系统

    基于socket.io的实时在线选座系统(demo) 前言 前段时间公司做一个关于剧院的项目,遇到了这样一种情况. 在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交 ...

  9. 基于 socket.io 的 AI 服务 杂谈

    为什么会想到来聊下这个话题. 前几天在公司的项目中,开发一个基于 socket.io 的直播 IM 功能. 直播分为两部分,一部分是比较昂贵的 视频推流, 另外一部分是 IM 即时聊天服务. 从这里开 ...

  10. Linux IO时事检测工具iostat

    Linux IO时事检测工具iostat iostat命令用于检测linux系统io设备的负载情况,运行iostat将显示自上次运行该命令以后的统计信息.用户可以通过指定统计的次数和时间来获得所需的统 ...

随机推荐

  1. vscode和phpStorm使用xdebug调试设置

    phpStorm http://www.cnblogs.com/cxscode/p/7045944.html http://www.cnblogs.com/cxscode/p/7050781.html ...

  2. Android端与Android端利用WIFI进行FTP通信

    一.客户端通信工具类: import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; im ...

  3. FineReport——JS二次开发(分页预览)

    BS访问某个cpt模板,报表servlet将会将cpt文件解析成对应的html,报表内容最终转换为一个table,位于id=content-container的div中. 在模板和html页面中,他们 ...

  4. JS实现全选与取消 Jquery判断checkbox是否被选中

    1.JS实现checkbox全选与取消 <body> <input type="checkbox" name="select_all"/> ...

  5. LeetCode解题报告—— Maximal Rectangle

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and ...

  6. hdu 1506(好题+DP或者RMQ)

    Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  7. poj 1182 (扩展并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 58979   Accepted: 17247 Description ...

  8. hdu 多校第一场

    1001 思路:打表可以发现只有3|n 和 4|n 的情况有解,判一下就好啦. #include<bits/stdc++.h> #define LL long long #define f ...

  9. 35.Spark系统运行内幕机制循环流程

    一:TaskScheduler原理解密 1,  DAGScheduler在提交TaskSet给底层调度器的时候是面向接口TaskScheduler的,这符合面向对象中依赖抽象而不依赖的原则,带来底层资 ...

  10. python 字符集转换-灰常慢

    代码 def toUni (text): str = text try: charstyle = chardet.detect(text) # print 'confidence: ', charst ...