proto文件
Example.proto
package example2.proto;
message BaseData {
required Header header = 1;
extensions 100 to 99999;
}
enum Header {
//装备升级
Msg1001 = 1001;
//装备穿戴
Msg1002 = 1002;
//添加好友
Msg1003 = 1003;
}
Friend.proto
package example2.proto;
import "example2/proto/Example.proto";
extend BaseData {
optional Receive1003 receive1003 = 10031;
optional Send1003 send1003 = 10032;
}
message Receive1003 {
required int32 friendId = 1;
}
message Send1003 {
required int32 friendId = 1;
required int32 state = 2;
}
NettyServer服务器
package example2.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.protobuf.ExtensionRegistry;
import example2.proto.Equip;
import example2.proto.Example;
import example2.proto.Friend;
import example2.server.handler.ProtoBufServerHandler;
public class NettyServer {
private static final int PORT = 1588;
private static Logger logger = Logger.getLogger(NettyServer.class.getName());
public void start(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.class);
b.option(ChannelOption.TCP_NODELAY, true);
b.option(ChannelOption.SO_BACKLOG, 1024);
b.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//decoded
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ExtensionRegistry registry = ExtensionRegistry.newInstance();
Equip.registerAllExtensions(registry);
Friend.registerAllExtensions(registry);
ch.pipeline().addLast(new ProtobufDecoder(Example.BaseData.getDefaultInstance(), registry));
//encoded
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
// 注册handler
ch.pipeline().addLast(new ProtoBufServerHandler());
}
});
//绑定端口 同步等待成功
ChannelFuture f = b.bind(port).sync();
//等待服务端监听端口关闭
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
logger.log(Level.INFO, "NettyServer start...");
new NettyServer().start(PORT);
}
}
ProtoBufServerHandler
package example2.server.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.HashMap;
import java.util.Map;
import example2.handlers.AbstractHandler;
import example2.handlers.EquipHandler;
import example2.handlers.FriendHandler;
import example2.proto.Example;
import example2.proto.Example.BaseData;
import example2.proto.Example.Header;
public class ProtoBufServerHandler extends SimpleChannelInboundHandler<Example.BaseData> {
//不同类型处理器,应该在服务器启动的时候就加载好对应关系
private static Map<Example.Header, AbstractHandler> headersMap;
static {
headersMap = new HashMap<Example.Header, AbstractHandler>();
headersMap.put(Header.Msg1001, new EquipHandler());
headersMap.put(Header.Msg1002, new EquipHandler());
headersMap.put(Header.Msg1003, new FriendHandler());
}
@Override
protected void messageReceived(ChannelHandlerContext ctx, BaseData baseData) throws Exception {
//需要放到单独的分发器中处理
AbstractHandler abstractHandler = headersMap.get(baseData.getHeader());
if (abstractHandler == null) {
System.err.println("没有找到消息处理器!!");
} else {
abstractHandler.handleMsg(ctx, baseData);
}
}
}
抽象处理器AbstractHandler
package example2.handlers;
import io.netty.channel.ChannelHandlerContext;
import example2.proto.Example.BaseData;
public abstract class AbstractHandler {
public void handleMsg(ChannelHandlerContext ctx, BaseData baseData) {
try {
Object object = handle(baseData);
ctx.channel().writeAndFlush(object);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 处理消息
*
* @param messageVo
*/
public abstract Object handle(BaseData baseData) throws Exception;
}
FriendHandler处理器
package example2.handlers;
import com.google.protobuf.InvalidProtocolBufferException;
import example2.proto.Example;
import example2.proto.Example.BaseData;
import example2.proto.Friend;
public class FriendHandler extends AbstractHandler {
@Override
public Object handle(BaseData baseData) throws InvalidProtocolBufferException {
switch (baseData.getHeader()) {
case Msg1003:
return addFriend(baseData);
}
return null;
}
private Object addFriend(BaseData baseData) {
Friend.Receive1003 extension = baseData.getExtension(Friend.receive1003);
System.err.println("1003消息接收成功,我要返回消息了----" + extension.getFriendId());
Friend.Send1003.Builder sendMsg = Friend.Send1003.newBuilder();
sendMsg.setFriendId(extension.getFriendId()).setState(0);
Example.BaseData.Builder builder = Example.BaseData.newBuilder();
builder.setHeader(Example.Header.Msg1003);
builder.setExtension(Friend.send1003, sendMsg.build());
return builder.build();
}
}
客户端跟服务器差不多的,就不上代码了。
这样一套消息处理,如果消息很多,感觉加起来会比较麻烦,大神给指点下怎么样优化可以使功能实现更简洁,万分感谢!
---------------------
作者:醉从零
来源:CSDN
原文:https://blog.csdn.net/woshiicesky/article/details/78044535
版权声明:本文为博主原创文章,转载请附上博文链接!
联系客服