0
点赞
收藏
分享

微信扫一扫

t-io客户端服务端的编写

洲行 2023-06-05 阅读 30


<dependency>
            <groupId>org.t-io</groupId>
            <artifactId>tio-core</artifactId>
            <version>3.7.4.v20210808-RELEASE</version>
        </dependency>

总共五个类。数据模型Packet、客户端处理器、客户端监听器、服务端处理器、服务端监听器。

  • 数据模型

package com.example.mindsa.client;


import lombok.Getter;
import lombok.Setter;
import org.tio.core.intf.Packet;
@Setter
@Getter
public class MindPackage extends Packet {
    private static final long serialVersionUID = -172060606924066412L;
    public static final int HEADER_LENGTH = 4;//消息头的长度
    public static final String CHARSET = "utf-8";
    private byte[] body;
}

  • 客户端处理器

package com.example.mindsa.client;

import org.tio.client.intf.ClientAioHandler;
import org.tio.core.ChannelContext;
import org.tio.core.TioConfig;
import org.tio.core.exception.TioDecodeException;
import org.tio.core.intf.Packet;

import java.nio.ByteBuffer;

public class ClientAioHandlerImpl implements ClientAioHandler {
    /**
     * 创建心跳包
     *
     * @param channelContext
     * @return
     * @author tanyaowu
     */
    @Override
    public Packet heartbeatPacket(ChannelContext channelContext) {
        return new MindPackage();
    }

    /**
     * 根据ByteBuffer解码成业务需要的Packet对象.
     * 如果收到的数据不全,导致解码失败,请返回null,在下次消息来时框架层会自动续上前面的收到的数据
     *
     * @param buffer         参与本次希望解码的ByteBuffer
     * @param limit          ByteBuffer的limit
     * @param position       ByteBuffer的position,不一定是0哦
     * @param readableLength ByteBuffer参与本次解码的有效数据(= limit - position)
     * @param channelContext
     * @return
     * @throws TioDecodeException
     */
    @Override
    public Packet decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext) throws TioDecodeException {
        //至少要有表示数据大小的四个字节。否则会因为无法知道数据大小而无法解包。
        if (readableLength < MindPackage.HEADER_LENGTH) {
            return null;
        }
        //获取存放在头部的四个字节,即数据字节的长度。这里要与服务器的编码约定一致:即头部4byte存放数据长度。
        int bodyLength = buffer.getInt();
        if (bodyLength < 0) {
            throw new TioDecodeException("头部4byte标识的数据长度是0");
        }
        //数据长度+头部4byte的长度大于可取得的数据长度,说明是半包,无法解析成完整的Packet。
        if (bodyLength + MindPackage.HEADER_LENGTH > readableLength) {
            return null;
        } else {
            MindPackage mindPackage = new MindPackage();
            byte[] bytes = new byte[bodyLength];
            //getInt已经把头部的四个字节读取掉了,position在4的位置,把剩下的数据装入容器
            buffer.get(bytes);
            mindPackage.setBody(bytes);
            return mindPackage;
        }
    }

    /**
     * 编码
     *
     * @param packet
     * @param tioConfig
     * @param channelContext
     * @return
     * @author: tanyaowu
     */
    @Override
    public ByteBuffer encode(Packet packet, TioConfig tioConfig, ChannelContext channelContext) {
        MindPackage mindPackage = (MindPackage) packet;
        byte[] body = mindPackage.getBody();
        int bodyLength = 0;
        if (body != null) {
            bodyLength = body.length;
        }
        //初始化ByteBuffer,长度为数据长度+标识数据长度的头部4byte字节。
        ByteBuffer byteBuffer = ByteBuffer.allocate(bodyLength + MindPackage.HEADER_LENGTH);
        byteBuffer.order(tioConfig.getByteOrder());
        //获取存放在头部的四个字节,即数据字节的长度。这里要与服务器的解码约定一致:即头部4byte存放数据长度。
        byteBuffer.putInt(bodyLength);
        if (body != null) {
            //存放数据
            byteBuffer.put(body);
        }
        return byteBuffer;
    }

    /**
     * 处理消息包
     *
     * @param packet
     * @param channelContext
     * @throws Exception
     * @author: tanyaowu
     */
    @Override
    public void handler(Packet packet, ChannelContext channelContext) throws Exception {
        //处理解码后的消息
        MindPackage mindPackage = (MindPackage) packet;
        //将byte数据转utf8字符串输出。
        System.out.println(new String(mindPackage.getBody(), MindPackage.CHARSET));
    }
}

  • 客户端监听器

package com.example.mindsa.client;

import org.tio.client.intf.ClientAioListener;
import org.tio.core.ChannelContext;
import org.tio.core.intf.Packet;

public class ClientAioListenerImpl implements ClientAioListener {
    @Override
    public void onAfterConnected(ChannelContext channelContext, boolean b, boolean b1) throws Exception {

    }

    @Override
    public void onAfterDecoded(ChannelContext channelContext, Packet packet, int i) throws Exception {

    }

    @Override
    public void onAfterReceivedBytes(ChannelContext channelContext, int i) throws Exception {

    }

    @Override
    public void onAfterSent(ChannelContext channelContext, Packet packet, boolean b) throws Exception {

    }

    @Override
    public void onAfterHandled(ChannelContext channelContext, Packet packet, long l) throws Exception {

    }

    @Override
    public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String s, boolean b) throws Exception {

    }
}

  • 服务端处理器

package com.example.mindsa.server;

import org.tio.core.ChannelContext;
import org.tio.core.TioConfig;
import org.tio.core.intf.Packet;
import org.tio.server.intf.ServerAioHandler;

import java.nio.ByteBuffer;

public class ServerAioHandlerImpl implements ServerAioHandler {

    /**
     * 根据ByteBuffer解码成业务需要的Packet对象.
     * 如果收到的数据不全,导致解码失败,请返回null,在下次消息来时框架层会自动续上前面的收到的数据
     *
     * @param buffer         参与本次希望解码的ByteBuffer
     * @param limit          ByteBuffer的limit
     * @param position       ByteBuffer的position,不一定是0哦
     * @param readableLength ByteBuffer参与本次解码的有效数据(= limit - position)
     * @param channelContext
     * @return
     */
    @Override
    public Packet decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext){

        return null;
    }

    /**
     * 编码
     *
     * @param packet
     * @param tioConfig
     * @param channelContext
     * @return
     * @author: tanyaowu
     */
    @Override
    public ByteBuffer encode(Packet packet, TioConfig tioConfig, ChannelContext channelContext) {
        return null;
    }

    /**
     * 处理消息包
     *
     * @param packet
     * @param channelContext
     * @throws Exception
     * @author: tanyaowu
     */
    @Override
    public void handler(Packet packet, ChannelContext channelContext) throws Exception {

    }
}

  • 服务端监听器

package com.example.mindsa.server;

import org.tio.core.ChannelContext;
import org.tio.core.intf.Packet;
import org.tio.server.intf.ServerAioListener;

public class ServerAioListenerImpl implements ServerAioListener {
    @Override
    public boolean onHeartbeatTimeout(ChannelContext channelContext, Long aLong, int i) {
        return false;
    }

    @Override
    public void onAfterConnected(ChannelContext channelContext, boolean b, boolean b1) throws Exception {

    }

    @Override
    public void onAfterDecoded(ChannelContext channelContext, Packet packet, int i) throws Exception {

    }

    @Override
    public void onAfterReceivedBytes(ChannelContext channelContext, int i) throws Exception {

    }

    @Override
    public void onAfterSent(ChannelContext channelContext, Packet packet, boolean b) throws Exception {

    }

    @Override
    public void onAfterHandled(ChannelContext channelContext, Packet packet, long l) throws Exception {

    }

    @Override
    public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String s, boolean b) throws Exception {

    }
}

启动客户端:

package com.example.mindsa.client;

import org.tio.client.ClientChannelContext;
import org.tio.client.ClientTioConfig;
import org.tio.client.ReconnConf;
import org.tio.client.TioClient;
import org.tio.core.Node;
import org.tio.core.Tio;

public class ClientStarter {
    public static void main(String[] args) throws Exception {
        ClientTioConfig clientTioConfig = new ClientTioConfig(new ClientAioHandlerImpl(), new ClientAioListenerImpl(), new ReconnConf());
        TioClient tioClient = new TioClient(clientTioConfig);
        ClientChannelContext connect = tioClient.connect(new Node("127.0.0.1", 8080));
        Tio.send(connect, new MindPackage());
    }
}

启动服务端

package com.example.mindsa.server;

import org.tio.server.ServerTioConfig;
import org.tio.server.TioServer;

import java.io.IOException;

public class ServerStarter {
    public static void main(String[] args) throws IOException {
        ServerTioConfig serverTioConfig = new ServerTioConfig(new ServerAioHandlerImpl(), new ServerAioListenerImpl());
        TioServer tioServer = new TioServer(serverTioConfig);
        tioServer.start(null, 8080);
    }
}

举报

相关推荐

0 条评论