【Mrpc】Demo3 基于netty的服务器和客户端。

Demo3实现如下功能,客户端发送一个Request对象(包含id,方法名,方法参数列表和调用参数列表)到服务端,服务端解析后调用客户端指定的方法,并返回一个Response对象(包含id,是否异常,异常,返回值)。客户端和服务端均基于netty实现。代码已上传到http://download.csdn.net/detail/mrbcy/9747693

要点解析

netty

这个真的很重要,具体的参考官方的guide吧,写得通俗易懂。http://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-9

对象的编解码

对象的编码和解码基本使用了Demo1中写的ProtoStuffUtil工具类,它可以将一个对象转换成byte[],或者从一个byte[]转换成一个对象。但是这里还有一个问题,由于tcp协议的特性,对方多次发送的数据我们可能一次性就收到了,或者发送了一次,但是我们分多次收到。为了解决这个问题,我在netty的编码部分做了处理,在对象的数据之前加了一个字节来存放对象数据的长度。解码部分也做了相应的处理,先读取数据的长度,然后等到有足够的数据再来读取对象。关键代码如下:

编码部分:

public void write(ChannelHandlerContext ctx, Object msg,
        ChannelPromise promise) throws Exception {
    if(clazz.isInstance(msg)){
        byte[] data = ProtostuffUtil.serializer(msg);
        ByteBuf encoded = ctx.alloc().buffer(data.length+4);
        encoded.writeInt(data.length);
        encoded.writeBytes(data);
        ctx.write(encoded, promise);
    }
}

解码部分:

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
        List<Object> out) throws Exception {
    // 前4字节记录长度
    if (in.readableBytes() < 4) {
        return;
    }
    in.markReaderIndex();
    int dataLength = in.readInt();
    if (dataLength < 0) {
        // 出错了
        ctx.close();
    }
    if (in.readableBytes() < dataLength) {
        in.resetReaderIndex();
        return;
    }

    //将ByteBuf转换为byte[]
    byte[] data = new byte[dataLength];
    in.readBytes(data);
    //将data转换成object
    @SuppressWarnings("unchecked")
    Object obj = ProtostuffUtil.deserializer(data, clazz);
    out.add(obj);
}

方法调用部分

这里涉及了反射的知识。服务端拿到客户端传入的request对象后,根据客户端指定的方法和参数来调用,然后把结果通过response发送给客户端。关键代码如下:

RpcResponse response = new RpcResponse();
try {
    RpcRequest request = (RpcRequest) msg;
    System.out.println("服务器收到调用请求:" + request);
    response.setId(request.getId());
    Method method = SampleServiceImpl.class.getDeclaredMethod(request.getMethodName(), request.getParamTypes());
    Object result = method.invoke(serviceImpl, request.getArgs());
    response.setResult(result);
} catch (Exception e) {
    response.setSuccess(false);
    response.setError(e);
}

写到这一步,框架的核心功能已经实现了一大部分,接下来就是用Spring了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值