limax协议解析StateTransportImpl

1.服务器与客户端注册att为NetTaskImpl

//网络连接时attach的是NetOperation子类
private void doAccept(SelectionKey key) throws IOException {
    ServerContextImpl context = (ServerContextImpl) key.attachment();
    NetOperation op = context.newInstance();
    SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
    channel.configureBlocking(false);
    op.attachKey(NetModel.pollPolicy.addChannel(channel, 0, op));
}

服务器启动时serverTask与ClientTask任务,两者的子类是NetTaskImpl

public static NetTask createClientTask(int rsize, int wsize, NetProcessor processor) {
    return new ClientTask(rsize, wsize, processor);
}

public static NetTask createServerTask(ServerContext context, NetProcessor processor) {
    return new ServerTask((ServerContextImpl) context, processor);
}

在PollTask收到消息时doRead逻辑

Throwable catched = null;
boolean needsche = false;
if (key.isReadable()) {
    try {
        doRead(key);
        needsche = true;
    } catch (Throwable e) {
        catched = e;
    }
}
if (key.isWritable()) {
    try {
        doWrite(key);
        needsche = true;
    } catch (Throwable e) {
        if (catched == null)
            catched = e;
    }
}
if (catched != null)
    doClose(key, catched);
else if (needsche)
    //在doRead之后会将attachement的类继续schedule
    ((NetOperation) key.attachment()).schedule();

NetTaskImpl中run方法

public void run() {
    switch (state) {
    case BINDKEY:
        try {
            synchronized (rbuf) {
                onBindKey();
                state = State.EXCHANGE;
            }
            total.incrementAndGet();
            running.incrementAndGet();
        } catch (Throwable t) {
            close(t);
        }
        break;
    case EXCHANGE:
        onExchange();
        if (!suspended)
            enableRead();
        break;
    case ABORT:
        state = State.CLOSED;
        onAbort();
        break;
    case CLOSING_FLUSH:
        int position = rbuf.position();
        if (position > 0)
            onExchange();
    case CLOSING:
        state = State.CLOSED;
        try {
            running.decrementAndGet();
            onUnbindKey();
        } catch (Throwable t) {
        }
        onClose();
    default:
    }
}   
//如果有信息交换时交由processor处理,这里是StateTransportImpl类
void onExchange() {
    try {
        processor.process(recv());
    } catch (Throwable e) {
        close(e, State.CLOSING);
    }
}

2.消息input,output处理

StateTransportImpl.process()

private volatile Codec input = NullCodec.getInstance();
private volatile Codec output = NullCodec.getInstance();
@Override
public void process(byte[] data) {
    if (data.length > 0) {
        if (Trace.isDebugEnabled())
            Trace.debug(manager + " " + this + " process size = " + data.length);
        try {
            input.update(data, 0, data.length);
            input.flush();
        } catch (Throwable e) {
            if (Trace.isInfoEnabled())
                Trace.info(manager + " " + this + " process Exception : " + Helper.toHexString(data), e);
            throw new RuntimeException(e);// force close
        }
    }
}

3.input.update中处理编码问题,limax提供了多种编码格式

//下面是输入和输出默认的编码格式,编码和解码顺序相反
@Override
public void setOutputSecurityCodec(byte[] key, boolean compress) {
    if (Trace.isDebugEnabled())
        Trace.debug(manager + " " + this + " setOutputSecurityCodec key = "
                + (key == null ? "" : Helper.toHexString(key)) + " compress = " + compress);
    Codec codec = new BufferedSink(new NetTaskCodecSink());
    if (null != key)
        try {
            codec = new Encrypt(codec, key);
        } catch (CodecException e) {
            if (Trace.isWarnEnabled())
                Trace.warn("setOutputEncrypt " + this, e);
        }
    if (compress)
        codec = new RFC2118Encode(codec);
    output = codec;
}

@Override
public void setInputSecurityCodec(byte[] key, boolean compress) {
    if (Trace.isDebugEnabled())
        Trace.debug(manager + " " + this + " setInputSecurityCodec key = "
                + (key == null ? "" : Helper.toHexString(key)) + " compress = " + compress);
    Codec codec = new CodecSink();
    if (compress || null != key)
        codec = new BufferedSink(codec);
    if (compress)
        codec = new RFC2118Decode(codec);
    if (null != key)
        try {
            codec = new Decrypt(codec, key);
        } catch (CodecException e) {
            if (Trace.isWarnEnabled())
                Trace.warn("setInputDecrypt " + this, e);
        }
    input = codec;
}

4.解密后处理消息

CoderSink.flush

@Override
public void flush() throws CodecException {
    try {
        if (os.remain() > 0)
            dispatch(state.decode(os, StateTransportImpl.this));
    } catch (Exception e) {
        throw new CodecException(e);
    }
}

Protocol

@Override
final void dispatch() {
    ((SupportDispatch) getManager()).dispatch(this, transport);
}

5.发送消息流程

Protocol.send()

public void send(Transport transport)
        throws InstantiationException, SizePolicyException, CodecException, ClassCastException {
    try {
        final Octets data = new OctetsStream().marshal(this);
        if (transport instanceof SupportStateCheck)
            ((SupportStateCheck) transport).check(getType(), data.size());
        ((SupportTypedDataTransfer) transport).send(getType(), data);
    } catch (InstantiationException e) {
        throw e;
    } catch (SizePolicyException e) {
        throw e;
    } catch (CodecException e) {
        throw e;
    } catch (ClassCastException e) {
        throw e;
    } catch (Throwable e) {
        throw new CodecException(e);
    }
}

StateTransportImpl 发送数据

void sendData(Octets data) throws CodecException {
    if (Trace.isDebugEnabled())
        Trace.debug(manager + " " + this + " sendData size = " + data.size());
    lock.lock();
    try {
        output.update(data.array(), 0, data.size());
        output.flush();
    } finally {
        lock.unlock();
    }
}

@Override
public void setOutputSecurityCodec(byte[] key, boolean compress) {
    if (Trace.isDebugEnabled())
        Trace.debug(manager + " " + this + " setOutputSecurityCodec key = "
                + (key == null ? "" : Helper.toHexString(key)) + " compress = " + compress);
    //NetTaskCodeSink最终会在update中发送数据
    Codec codec = new BufferedSink(new NetTaskCodecSink());
    if (null != key)
        try {
            codec = new Encrypt(codec, key);
        } catch (CodecException e) {
            if (Trace.isWarnEnabled())
                Trace.warn("setOutputEncrypt " + this, e);
        }
    if (compress)
        codec = new RFC2118Encode(codec);
    output = codec;
}

NetTaskCodecSink 发送数据

private class NetTaskCodecSink implements Codec {
    @Override
    public void update(byte c) throws CodecException {
        update(new byte[] { c }, 0, 1);
    }

    @Override
    public void update(byte[] data, int off, int len) throws CodecException {
        if (nettask == null)
            throw new CodecException("nettask has been closed.");
        if (config.isCheckOutputBuffer()) {
            long sendbuffersize = nettask.getSendBufferSize() + len;
            long configsize = config.getOutputBufferSize();
            if (sendbuffersize > configsize) {
                if (Trace.isWarnEnabled())
                    Trace.warn(manager + " " + this + " send buffer is full! sendbuffersize " + sendbuffersize + " "
                            + configsize);
                close();
                return;
            }
        }
        if (Trace.isDebugEnabled())
            Trace.debug(manager + " " + this + " send " + Helper.toHexString(data, off, len));
        nettask.send(data, off, len);
    }

    @Override
    public void flush() throws CodecException {
        if (nettask == null)
            throw new CodecException("nettask has been closed.");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值