• 基于t-io的MI工具实现


    原文: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;
    	}
    	
    	
    	
    	
    
    }
  • 相关阅读:
    Lua学习笔记(二):基本语法
    Lua学习笔记(一):搭建开发环境
    C#学习笔记(十六):Attribute
    [U3D Demo] 手机FPS射击游戏
    C#学习笔记(十五):预处理指令
    js 树菜单 ztree
    jquery flexslider 轮播插件
    浏览器 本地预览图片 window.url.createobjecturl
    mouseover mouseenter mouseout mouseleave
    jquery checkbox问题
  • 原文地址:https://www.cnblogs.com/shihaiming/p/8630024.html
Copyright © 2020-2023  润新知