Repository: BazingaLyn/netty-study Branch: master Commit: 0b6ad325ed9c Files: 149 Total size: 357.3 KB Directory structure: gitextract_h9fdvoav/ ├── README.md ├── pom.xml └── src/ └── main/ ├── java/ │ └── com/ │ └── lyncc/ │ └── netty/ │ ├── attributeMap/ │ │ ├── AttributeMapConstant.java │ │ ├── HelloWorld2ClientHandler.java │ │ ├── HelloWorldClient.java │ │ ├── HelloWorldClientHandler.java │ │ ├── HelloWorldServer.java │ │ ├── HelloWorldServerHandler.java │ │ └── NettyChannel.java │ ├── codec/ │ │ ├── custom/ │ │ │ ├── ProtocolDecoder.java │ │ │ ├── ProtocolEncoder.java │ │ │ ├── ProtocolHeader.java │ │ │ └── ProtocolMsg.java │ │ ├── jackson/ │ │ │ ├── JacksonClient.java │ │ │ ├── JacksonClientHandler.java │ │ │ ├── JacksonClientHandlerInitializer.java │ │ │ ├── JacksonServer.java │ │ │ ├── JacksonServerHandler.java │ │ │ ├── JacksonServerHandlerInitializer.java │ │ │ ├── User.java │ │ │ ├── UserDecoder.java │ │ │ ├── UserEncoder.java │ │ │ └── UserMapper.java │ │ ├── lengthFieldBasedFrame/ │ │ │ ├── CustomClient.java │ │ │ ├── CustomClientHandler.java │ │ │ ├── CustomDecoder.java │ │ │ ├── CustomEncoder.java │ │ │ ├── CustomMsg.java │ │ │ ├── CustomServer.java │ │ │ └── CustomServerHandler.java │ │ └── protobuf/ │ │ ├── SubReqClient.java │ │ ├── SubReqClientHandler.java │ │ ├── SubReqServer.java │ │ ├── SubReqServerHandler.java │ │ ├── SubscribeReq.proto │ │ ├── SubscribeReqProto.java │ │ ├── SubscribeResp.proto │ │ ├── SubscribeRespProto.java │ │ ├── TestSubscribeReqProto.java │ │ └── demo/ │ │ ├── ProtoBufClient.java │ │ ├── ProtoBufClientHandler.java │ │ ├── ProtoBufServer.java │ │ ├── ProtoBufServerHandler.java │ │ ├── RichMan.proto │ │ └── RichManProto.java │ ├── component/ │ │ ├── channelhandler/ │ │ │ ├── BaseClient.java │ │ │ ├── BaseClient1Handler.java │ │ │ ├── BaseClient2Handler.java │ │ │ ├── BaseServer.java │ │ │ └── BaseServerHandler.java │ │ └── simplehandler/ │ │ ├── BaseClient.java │ │ ├── BaseClientHandler.java │ │ ├── BaseServer.java │ │ └── BaseServerHandler.java │ ├── concept/ │ │ └── HelloWorldConcept.java │ ├── heartbeat/ │ │ ├── BaseClient.java │ │ ├── BaseClientHandler.java │ │ ├── BaseServer.java │ │ └── BaseServerHandler.java │ ├── heartbeat2/ │ │ ├── AskMsg.java │ │ ├── AskParams.java │ │ ├── BaseMsg.java │ │ ├── Constants.java │ │ ├── LoginMsg.java │ │ ├── MsgType.java │ │ ├── NettyChannelMap.java │ │ ├── NettyClientBootstrap.java │ │ ├── NettyClientHandler.java │ │ ├── NettyServerBootstrap.java │ │ ├── NettyServerHandler.java │ │ ├── PingMsg.java │ │ ├── ReplyBody.java │ │ ├── ReplyClientBody.java │ │ ├── ReplyMsg.java │ │ └── ReplyServerBody.java │ ├── heartbeats/ │ │ ├── HeartBeatClientHandler.java │ │ ├── HeartBeatServer.java │ │ ├── HeartBeatServerHandler.java │ │ └── HeartBeatsClient.java │ ├── hello/ │ │ ├── HelloWorldClient.java │ │ ├── HelloWorldClientHandler.java │ │ ├── HelloWorldServer.java │ │ └── HelloWorldServerHandler.java │ ├── idle/ │ │ ├── AcceptorIdleStateTrigger.java │ │ ├── ChannelHandlerHolder.java │ │ ├── ConnectionWatchdog.java │ │ ├── ConnectorIdleStateTrigger.java │ │ ├── HeartBeatClientHandler.java │ │ ├── HeartBeatServer.java │ │ ├── HeartBeatServerHandler.java │ │ └── HeartBeatsClient.java │ ├── keepalive/ │ │ ├── Constants.java │ │ ├── Heartbeat.java │ │ ├── KeepAliveClient.java │ │ ├── KeepAliveMessage.java │ │ ├── KeepAliveServer.java │ │ ├── KeepAliveServerInitializer.java │ │ └── Utils.java │ ├── nio/ │ │ ├── EchoClient.java │ │ ├── MultiPortEchoServer.java │ │ └── package-info.java │ ├── production/ │ │ ├── ChannelHandlerHolder.java │ │ ├── ConnectionWatchdog.java │ │ ├── client/ │ │ │ └── connector/ │ │ │ ├── ClientConnector.java │ │ │ ├── ConnectorIdleStateTrigger.java │ │ │ ├── DefaultCommonClientConnector.java │ │ │ ├── NettyClientConnector.java │ │ │ └── package-info.java │ │ ├── common/ │ │ │ ├── Acknowledge.java │ │ │ ├── Heartbeats.java │ │ │ ├── Message.java │ │ │ ├── NativeSupport.java │ │ │ ├── NettyCommonProtocol.java │ │ │ ├── NettyEvent.java │ │ │ ├── NettyEventType.java │ │ │ ├── ServiceThread.java │ │ │ ├── exception/ │ │ │ │ └── ConnectFailedException.java │ │ │ └── package-info.java │ │ ├── example/ │ │ │ ├── ClientConnectorStartup.java │ │ │ ├── SrvAcceptorStartup.java │ │ │ └── package-info.java │ │ ├── serializer/ │ │ │ ├── Serializer.java │ │ │ ├── SerializerHolder.java │ │ │ └── protostuff/ │ │ │ └── ProtoStuffSerializer.java │ │ └── srv/ │ │ └── acceptor/ │ │ ├── AcceptorIdleStateTrigger.java │ │ ├── AcknowledgeEncoder.java │ │ ├── ChannelEventListener.java │ │ ├── DefaultCommonSrvAcceptor.java │ │ ├── DefaultSrvAcceptor.java │ │ ├── NettySrvAcceptor.java │ │ ├── SrvAcceptor.java │ │ └── package-info.java │ └── stickpackage/ │ ├── correct/ │ │ ├── BaseClient.java │ │ ├── BaseClientHandler.java │ │ ├── BaseServer.java │ │ └── BaseServerHandler.java │ ├── delimiter/ │ │ ├── BaseClient.java │ │ ├── BaseClientHandler.java │ │ ├── BaseServer.java │ │ └── BaseServerHandler.java │ ├── error/ │ │ ├── BaseClient.java │ │ ├── BaseClientHandler.java │ │ ├── BaseServer.java │ │ └── BaseServerHandler.java │ └── myself/ │ ├── BaseClient.java │ ├── BaseClientHandler.java │ ├── BaseServer.java │ └── BaseServerHandler.java └── resources/ └── logback.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # netty-study netty4.x知识点学习 ### 1) [生产级别的心跳重连](https://github.com/BazingaLyn/netty-study/tree/master/src/main/java/com/lyncc/netty/idle) ### 2) [比较规范的netty的C/S端编写](https://github.com/BazingaLyn/netty-study/tree/master/src/main/java/com/lyncc/netty/production) 1)有心跳机制 2)有ACK检验机制 3)有重连机制 4)自定义交互协议 (代码是从Jupiter和RocketMQ中截出) ================================================ FILE: pom.xml ================================================ 4.0.0 com.study netty-study 0.0.1-SNAPSHOT jar netty-study http://maven.apache.org UTF-8 2.6.3 1.7.5 junit junit 4.10 test org.slf4j slf4j-api ${slf4j.version} io.netty netty-all 4.0.21.Final com.fasterxml.jackson.core jackson-core ${version.jackson.core} com.fasterxml.jackson.core jackson-databind ${version.jackson.core} com.google.protobuf protobuf-java 2.6.1 io.protostuff protostuff-core 1.3.5 io.protostuff protostuff-runtime 1.3.5 org.objenesis objenesis 2.1 ch.qos.logback logback-classic 1.0.13 ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/AttributeMapConstant.java ================================================ package com.lyncc.netty.attributeMap; import io.netty.util.AttributeKey; public class AttributeMapConstant { public static final AttributeKey NETTY_CHANNEL_KEY = AttributeKey.valueOf("netty.channel"); } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/HelloWorld2ClientHandler.java ================================================ package com.lyncc.netty.attributeMap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.Attribute; import io.netty.util.AttributeKey; import java.util.HashSet; public class HelloWorld2ClientHandler extends ChannelInboundHandlerAdapter { public static final AttributeKey> NETTY_CHANNEL_KEY1 = AttributeKey.valueOf("netty.channel1"); @Override public void channelActive(ChannelHandlerContext ctx) { Attribute> attr = ctx.channel().attr(NETTY_CHANNEL_KEY1); HashSet sets = attr.get(); if (sets == null) { HashSet newSet = new HashSet(); sets = attr.setIfAbsent(newSet); if(null == sets){ System.out.println("GGGGGGGGGGGGGGGGGGGGGG NULLLLLLLLLLL"); sets = newSet; } HashSet sets2 = attr.get(); System.out.println("RRRRRRRRRRRRRRRRR ==="+sets2.size()); for(Integer i :sets2){ System.out.println("value is GGGGGGGGGGG===="+i); } } sets.add(1); HashSet sets3 = attr.get(); System.out.println("RRRRRRRRRRRRRRRRR2 ==="+sets3.size()); System.out.println("HelloWorldC2ientHandler Active"); ctx.fireChannelActive(); } public static void main(String[] args) { Student student = new Student("1", 21); Student s =student; s.setAge(88); System.out.println(student.getAge()); } static class Student { String id; int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String id, int age) { super(); this.id = id; this.age = age; } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { Attribute> attr = ctx.channel().attr(NETTY_CHANNEL_KEY1); HashSet sets = attr.get(); if (sets == null) { System.out.println("没有值啊"); }else{ for(Integer i :sets){ System.out.println("value is ===="+i); } } System.out.println("HelloWorldClientHandler read Message:" + msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/HelloWorldClient.java ================================================ package com.lyncc.netty.attributeMap; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class HelloWorldClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { initChannel(); } public static void initChannel() throws InterruptedException{ // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast(new HelloWorldClientHandler()); p.addLast(new HelloWorld2ClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("hello Netty,Test attributeMap"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/HelloWorldClientHandler.java ================================================ package com.lyncc.netty.attributeMap; import static com.lyncc.netty.attributeMap.AttributeMapConstant.NETTY_CHANNEL_KEY; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.Attribute; import java.util.Date; public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { Attribute attr = ctx.channel().attr(NETTY_CHANNEL_KEY); NettyChannel nChannel = attr.get(); if (nChannel == null) { NettyChannel newNChannel = new NettyChannel("HelloWorld0Client", new Date()); nChannel = attr.setIfAbsent(newNChannel); } else { System.out.println("channelActive attributeMap 中是有值的"); System.out.println(nChannel.getName() + "=======" + nChannel.getCreateDate()); } System.out.println("HelloWorldC0ientHandler Active"); ctx.fireChannelActive(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { Attribute attr = ctx.channel().attr(NETTY_CHANNEL_KEY); NettyChannel nChannel = attr.get(); if (nChannel == null) { NettyChannel newNChannel = new NettyChannel("HelloWorld0Client", new Date()); nChannel = attr.setIfAbsent(newNChannel); } else { System.out.println("channelRead attributeMap 中是有值的"); System.out.println(nChannel.getName() + "=======" + nChannel.getCreateDate()); } System.out.println("HelloWorldClientHandler read Message:" + msg); ctx.fireChannelRead(msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/HelloWorldServer.java ================================================ package com.lyncc.netty.attributeMap; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress; public class HelloWorldServer { private int port; public HelloWorldServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HelloWorldServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new HelloWorldServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/HelloWorldServerHandler.java ================================================ package com.lyncc.netty.attributeMap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class HelloWorldServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString()); ctx.write("server write"+msg); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/attributeMap/NettyChannel.java ================================================ package com.lyncc.netty.attributeMap; import java.util.Date; public class NettyChannel { private String name; private Date createDate; public NettyChannel(String name,Date createDate) { this.name = name; this.createDate = createDate; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/custom/ProtocolDecoder.java ================================================ package com.lyncc.netty.codec.custom; public class ProtocolDecoder{ } ================================================ FILE: src/main/java/com/lyncc/netty/codec/custom/ProtocolEncoder.java ================================================ package com.lyncc.netty.codec.custom; import java.nio.charset.Charset; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; public class ProtocolEncoder extends MessageToByteEncoder { @Override protected void encode(ChannelHandlerContext ctx, ProtocolMsg msg, ByteBuf out) throws Exception { if (null == msg || null == msg.getProtocolHeader()) { throw new Exception("msg is null"); } ProtocolHeader header = msg.getProtocolHeader(); String body = msg.getBody(); byte[] bodyBytes = body.getBytes(Charset.forName("utf-8")); int bodySize = bodyBytes.length; out.writeByte(header.getMagic()); out.writeByte(header.getMsgType()); out.writeShort(header.getReserve()); out.writeShort(header.getSn()); out.writeInt(bodySize); out.writeBytes(bodyBytes); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/custom/ProtocolHeader.java ================================================ package com.lyncc.netty.codec.custom; public class ProtocolHeader { private byte magic; private byte msgType; private short reserve; private short sn; private int len; public ProtocolHeader() { } public byte getMagic() { return magic; } public void setMagic(byte magic) { this.magic = magic; } public byte getMsgType() { return msgType; } public void setMsgType(byte msgType) { this.msgType = msgType; } public short getReserve() { return reserve; } public void setReserve(short reserve) { this.reserve = reserve; } public short getSn() { return sn; } public void setSn(short sn) { this.sn = sn; } public int getLen() { return len; } public void setLen(int len) { this.len = len; } public ProtocolHeader(byte magic, byte msgType, short reserve, short sn, int len) { this.magic = magic; this.msgType = msgType; this.reserve = reserve; this.sn = sn; this.len = len; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/custom/ProtocolMsg.java ================================================ package com.lyncc.netty.codec.custom; public class ProtocolMsg { private ProtocolHeader protocolHeader = new ProtocolHeader(); private String body; public ProtocolMsg() { } public ProtocolHeader getProtocolHeader() { return protocolHeader; } public void setProtocolHeader(ProtocolHeader protocolHeader) { this.protocolHeader = protocolHeader; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonClient.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import java.util.ArrayList; import java.util.List; public class JacksonClient { private final String host; private final int port; public JacksonClient(String host, int port){ this.host = host; this.port = port; } public static void main(String[] args) throws Exception{ new JacksonClient("localhost", 8082).run(); } public void run() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new JacksonClientHandlerInitializer()); Channel channel = bootstrap.connect(host, port).sync().channel(); // 发送对象 User user = new User(); user.setId(1); user.setAge(21); user.setName("BazingaLyncc"); List friends = new ArrayList(); friends.add("TED"); friends.add("MISS"); user.setFriends(friends); channel.write(user); channel.flush(); // 等待连接关闭 channel.closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonClientHandler.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class JacksonClientHandler extends SimpleChannelInboundHandler{ @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { String jsonString = ""; if (msg instanceof User) { User user = (User) msg; jsonString = UserMapper.getInstance().writeValueAsString(user); } else { jsonString = UserMapper.getInstance().writeValueAsString(msg); } System.out.println("Client get msg form Server -" + jsonString); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonClientHandlerInitializer.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; public class JacksonClientHandlerInitializer extends ChannelInitializer{ @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new UserDecoder(User.class)); pipeline.addLast(new UserEncoder()); pipeline.addLast(new JacksonClientHandler()); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonServer.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public class JacksonServer { static final int PORT = 8082; public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap().group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .childOption(ChannelOption.SO_KEEPALIVE, true) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new JacksonServerHandlerInitializer()); ChannelFuture f = serverBootstrap.bind(PORT).sync(); System.out.println("Server start listen at " + PORT ); f.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonServerHandler.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class JacksonServerHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { String jsonString = ""; if (msg instanceof User) { User user = (User)msg; ctx.writeAndFlush(user); jsonString = UserMapper.getInstance().writeValueAsString(user); } else { ctx.writeAndFlush(msg); jsonString = UserMapper.getInstance().writeValueAsString(msg); } System.out.println("Server get msg form Client -" + jsonString); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { Channel incoming = ctx.channel(); System.out.println("SimpleChatClient:"+incoming.remoteAddress()+"异常"); cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/JacksonServerHandlerInitializer.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; public class JacksonServerHandlerInitializer extends ChannelInitializer{ @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new UserDecoder(User.class)); pipeline.addLast(new UserEncoder()); pipeline.addLast(new JacksonServerHandler()); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/User.java ================================================ package com.lyncc.netty.codec.jackson; import java.util.List; public class User { private Integer id; private String name; private Integer age; private List friends; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public List getFriends() { return friends; } public void setFriends(List friends) { this.friends = friends; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/UserDecoder.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import java.util.List; public class UserDecoder extends ByteToMessageDecoder { private final Class clazz; public UserDecoder(Class clazz) { this.clazz = clazz; } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { ByteBufInputStream byteBufInputStream = new ByteBufInputStream(in); out.add(UserMapper.getInstance().readValue(byteBufInputStream, clazz)); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/UserEncoder.java ================================================ package com.lyncc.netty.codec.jackson; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; public class UserEncoder extends MessageToByteEncoder{ @Override protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception { ByteBufOutputStream byteBufOutputStream = new ByteBufOutputStream(out); UserMapper.getInstance().writeValue(byteBufOutputStream, msg); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/jackson/UserMapper.java ================================================ package com.lyncc.netty.codec.jackson; import com.fasterxml.jackson.databind.ObjectMapper; public class UserMapper { private static final ObjectMapper MAPPER = new ObjectMapper(); public static ObjectMapper getInstance() { return MAPPER; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomClient.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; public class CustomClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new CustomEncoder()); ch.pipeline().addLast(new CustomClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomClientHandler.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class CustomClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { CustomMsg customMsg = new CustomMsg((byte)0xAB, (byte)0xCD, "Hello,Netty".length(), "Hello,Netty"); ctx.writeAndFlush(customMsg); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomDecoder.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; public class CustomDecoder extends LengthFieldBasedFrameDecoder { //判断传送客户端传送过来的数据是否按照协议传输,头部信息的大小应该是 byte+byte+int = 1+1+4 = 6 private static final int HEADER_SIZE = 6; private byte type; private byte flag; private int length; private String body; /** * * @param maxFrameLength 解码时,处理每个帧数据的最大长度 * @param lengthFieldOffset 该帧数据中,存放该帧数据的长度的数据的起始位置 * @param lengthFieldLength 记录该帧数据长度的字段本身的长度 * @param lengthAdjustment 修改帧数据长度字段中定义的值,可以为负数 * @param initialBytesToStrip 解析的时候需要跳过的字节数 * @param failFast 为true,当frame长度超过maxFrameLength时立即报TooLongFrameException异常,为false,读取完整个帧再报异常 */ public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast); } @Override protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { if (in == null) { return null; } if (in.readableBytes() < HEADER_SIZE) { throw new Exception("可读信息段比头部信息都小,你在逗我?"); } //注意在读的过程中,readIndex的指针也在移动 type = in.readByte(); flag = in.readByte(); length = in.readInt(); if (in.readableBytes() < length) { throw new Exception("body字段你告诉我长度是"+length+",但是真实情况是没有这么多,你又逗我?"); } ByteBuf buf = in.readBytes(length); byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); body = new String(req, "UTF-8"); CustomMsg customMsg = new CustomMsg(type,flag,length,body); return customMsg; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomEncoder.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; import java.nio.charset.Charset; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; public class CustomEncoder extends MessageToByteEncoder { @Override protected void encode(ChannelHandlerContext ctx, CustomMsg msg, ByteBuf out) throws Exception { if(null == msg){ throw new Exception("msg is null"); } String body = msg.getBody(); byte[] bodyBytes = body.getBytes(Charset.forName("utf-8")); out.writeByte(msg.getType()); out.writeByte(msg.getFlag()); out.writeInt(bodyBytes.length); out.writeBytes(bodyBytes); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomMsg.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; public class CustomMsg { //类型 系统编号 0xAB 表示A系统,0xBC 表示B系统 private byte type; //信息标志 0xAB 表示心跳包 0xBC 表示超时包 0xCD 业务信息包 private byte flag; //主题信息的长度 private int length; //主题信息 private String body; public CustomMsg() { } public CustomMsg(byte type, byte flag, int length, String body) { this.type = type; this.flag = flag; this.length = length; this.body = body; } public byte getType() { return type; } public void setType(byte type) { this.type = type; } public byte getFlag() { return flag; } public void setFlag(byte flag) { this.flag = flag; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomServer.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; 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 java.net.InetSocketAddress; public class CustomServer { private static final int MAX_FRAME_LENGTH = 1024 * 1024; private static final int LENGTH_FIELD_LENGTH = 4; private static final int LENGTH_FIELD_OFFSET = 2; private static final int LENGTH_ADJUSTMENT = 0; private static final int INITIAL_BYTES_TO_STRIP = 0; private int port; public CustomServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new CustomDecoder(MAX_FRAME_LENGTH,LENGTH_FIELD_LENGTH,LENGTH_FIELD_OFFSET,LENGTH_ADJUSTMENT,INITIAL_BYTES_TO_STRIP,false)); ch.pipeline().addLast(new CustomServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new CustomServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/lengthFieldBasedFrame/CustomServerHandler.java ================================================ package com.lyncc.netty.codec.lengthFieldBasedFrame; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class CustomServerHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if(msg instanceof CustomMsg) { CustomMsg customMsg = (CustomMsg)msg; System.out.println("Client->Server:"+ctx.channel().remoteAddress()+" send "+customMsg.getBody()); } } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubReqClient.java ================================================ /* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.lyncc.netty.codec.protobuf; import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; 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; /** * @author lilinfeng * @date 2014年2月14日 * @version 1.0 */ public class SubReqClient { public void connect(int port, String host) throws Exception { // 配置客户端NIO线程组 EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast(new ProtobufDecoder(SubscribeRespProto.SubscribeResp.getDefaultInstance())); ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast(new ProtobufEncoder()); ch.pipeline().addLast(new SubReqClientHandler()); } }); // 发起异步连接操作 ChannelFuture f = b.connect(host, port).sync(); // 当代客户端链路关闭 f.channel().closeFuture().sync(); } finally { // 优雅退出,释放NIO线程组 group.shutdownGracefully(); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new SubReqClient().connect(port, "127.0.0.1"); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubReqClientHandler.java ================================================ /* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.lyncc.netty.codec.protobuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.ArrayList; import java.util.List; /** * @author lilinfeng * @date 2014年2月14日 * @version 1.0 */ public class SubReqClientHandler extends ChannelInboundHandlerAdapter { /** * Creates a client-side handler. */ public SubReqClientHandler() { } @Override public void channelActive(ChannelHandlerContext ctx) { for (int i = 0; i < 10; i++) { ctx.write(subReq(i)); } ctx.flush(); } private SubscribeReqProto.SubscribeReq subReq(int i) { SubscribeReqProto.SubscribeReq.Builder builder = SubscribeReqProto.SubscribeReq.newBuilder(); builder.setSubReqID(i); builder.setUserName("Lilinfeng"); builder.setProductName("Netty Book For Protobuf"); List address = new ArrayList(); address.add("NanJing YuHuaTai"); address.add("BeiJing LiuLiChang"); address.add("ShenZhen HongShuLin"); builder.addAllAddress(address); return builder.build(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Receive server response : [" + msg + "]"); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubReqServer.java ================================================ package com.lyncc.netty.codec.protobuf; 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 io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public class SubReqServer { public void bind(int port) throws Exception { // 配置服务端的NIO线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast(new ProtobufDecoder(SubscribeReqProto.SubscribeReq.getDefaultInstance())); ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast(new ProtobufEncoder()); ch.pipeline().addLast(new SubReqServerHandler()); } }); // 绑定端口,同步等待成功 ChannelFuture f = b.bind(port).sync(); System.out.println("init start"); // 等待服务端监听端口关闭 f.channel().closeFuture().sync(); } finally { // 优雅退出,释放线程池资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new SubReqServer().bind(port); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubReqServerHandler.java ================================================ /* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.lyncc.netty.codec.protobuf; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @Sharable public class SubReqServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { SubscribeReqProto.SubscribeReq req = (SubscribeReqProto.SubscribeReq) msg; if ("Lilinfeng".equalsIgnoreCase(req.getUserName())) { System.out.println("Service accept client subscribe req : [" + req.toString() + "]"); ctx.writeAndFlush(resp(req.getSubReqID())); } } private SubscribeRespProto.SubscribeResp resp(int subReqID) { SubscribeRespProto.SubscribeResp.Builder builder = SubscribeRespProto.SubscribeResp.newBuilder(); builder.setSubReqID(subReqID); builder.setRespCode(0); builder.setDesc("Netty book order succeed, 3 days later, sent to the designated address"); return builder.build(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close();// 发生异常,关闭链路 } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubscribeReq.proto ================================================ package netty; option java_package = "com.lyncc.netty.codec.protobuf"; option java_outer_classname = "SubscribeReqProto"; message SubscribeReq{ required int32 subReqID = 1; required string userName = 2; required string productName = 3; repeated string address = 4; } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubscribeReqProto.java ================================================ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: SubscribeReq.proto package com.lyncc.netty.codec.protobuf; public final class SubscribeReqProto { private SubscribeReqProto() { } public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { } public interface SubscribeReqOrBuilder extends // @@protoc_insertion_point(interface_extends:netty.SubscribeReq) com.google.protobuf.MessageOrBuilder { /** * required int32 subReqID = 1; */ boolean hasSubReqID(); /** * required int32 subReqID = 1; */ int getSubReqID(); /** * required string userName = 2; */ boolean hasUserName(); /** * required string userName = 2; */ java.lang.String getUserName(); /** * required string userName = 2; */ com.google.protobuf.ByteString getUserNameBytes(); /** * required string productName = 3; */ boolean hasProductName(); /** * required string productName = 3; */ java.lang.String getProductName(); /** * required string productName = 3; */ com.google.protobuf.ByteString getProductNameBytes(); /** * repeated string address = 4; */ com.google.protobuf.ProtocolStringList getAddressList(); /** * repeated string address = 4; */ int getAddressCount(); /** * repeated string address = 4; */ java.lang.String getAddress(int index); /** * repeated string address = 4; */ com.google.protobuf.ByteString getAddressBytes(int index); } /** * Protobuf type {@code netty.SubscribeReq} */ public static final class SubscribeReq extends com.google.protobuf.GeneratedMessage implements // @@protoc_insertion_point(message_implements:netty.SubscribeReq) SubscribeReqOrBuilder { // Use SubscribeReq.newBuilder() to construct. private SubscribeReq(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); this.unknownFields = builder.getUnknownFields(); } private SubscribeReq(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } private static final SubscribeReq defaultInstance; public static SubscribeReq getDefaultInstance() { return defaultInstance; } public SubscribeReq getDefaultInstanceForType() { return defaultInstance; } private final com.google.protobuf.UnknownFieldSet unknownFields; @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private SubscribeReq(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { initFields(); int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet .newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; default: { if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { done = true; } break; } case 8: { bitField0_ |= 0x00000001; subReqID_ = input.readInt32(); break; } case 18: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000002; userName_ = bs; break; } case 26: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000004; productName_ = bs; break; } case 34: { com.google.protobuf.ByteString bs = input.readBytes(); if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { address_ = new com.google.protobuf.LazyStringArrayList(); mutable_bitField0_ |= 0x00000008; } address_.add(bs); break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { address_ = address_.getUnmodifiableView(); } this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.internal_static_netty_SubscribeReq_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.internal_static_netty_SubscribeReq_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.class, com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.Builder.class); } public static com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { public SubscribeReq parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new SubscribeReq(input, extensionRegistry); } }; @java.lang.Override public com.google.protobuf.Parser getParserForType() { return PARSER; } private int bitField0_; public static final int SUBREQID_FIELD_NUMBER = 1; private int subReqID_; /** * required int32 subReqID = 1; */ public boolean hasSubReqID() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 subReqID = 1; */ public int getSubReqID() { return subReqID_; } public static final int USERNAME_FIELD_NUMBER = 2; private java.lang.Object userName_; /** * required string userName = 2; */ public boolean hasUserName() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required string userName = 2; */ public java.lang.String getUserName() { java.lang.Object ref = userName_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { userName_ = s; } return s; } } /** * required string userName = 2; */ public com.google.protobuf.ByteString getUserNameBytes() { java.lang.Object ref = userName_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); userName_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } public static final int PRODUCTNAME_FIELD_NUMBER = 3; private java.lang.Object productName_; /** * required string productName = 3; */ public boolean hasProductName() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * required string productName = 3; */ public java.lang.String getProductName() { java.lang.Object ref = productName_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { productName_ = s; } return s; } } /** * required string productName = 3; */ public com.google.protobuf.ByteString getProductNameBytes() { java.lang.Object ref = productName_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); productName_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } public static final int ADDRESS_FIELD_NUMBER = 4; private com.google.protobuf.LazyStringList address_; /** * repeated string address = 4; */ public com.google.protobuf.ProtocolStringList getAddressList() { return address_; } /** * repeated string address = 4; */ public int getAddressCount() { return address_.size(); } /** * repeated string address = 4; */ public java.lang.String getAddress(int index) { return address_.get(index); } /** * repeated string address = 4; */ public com.google.protobuf.ByteString getAddressBytes(int index) { return address_.getByteString(index); } private void initFields() { subReqID_ = 0; userName_ = ""; productName_ = ""; address_ = com.google.protobuf.LazyStringArrayList.EMPTY; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; if (!hasSubReqID()) { memoizedIsInitialized = 0; return false; } if (!hasUserName()) { memoizedIsInitialized = 0; return false; } if (!hasProductName()) { memoizedIsInitialized = 0; return false; } memoizedIsInitialized = 1; return true; } public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeInt32(1, subReqID_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeBytes(2, getUserNameBytes()); } if (((bitField0_ & 0x00000004) == 0x00000004)) { output.writeBytes(3, getProductNameBytes()); } for (int i = 0; i < address_.size(); i++) { output.writeBytes(4, address_.getByteString(i)); } getUnknownFields().writeTo(output); } private int memoizedSerializedSize = -1; public int getSerializedSize() { int size = memoizedSerializedSize; if (size != -1) return size; size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, subReqID_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream.computeBytesSize(2, getUserNameBytes()); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream.computeBytesSize(3, getProductNameBytes()); } { int dataSize = 0; for (int i = 0; i < address_.size(); i++) { dataSize += com.google.protobuf.CodedOutputStream.computeBytesSizeNoTag(address_.getByteString(i)); } size += dataSize; size += 1 * getAddressList().size(); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; } private static final long serialVersionUID = 0L; @java.lang.Override protected java.lang.Object writeReplace() throws java.io.ObjectStreamException { return super.writeReplace(); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom(java.io.InputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseDelimitedFrom( java.io.InputStream input) throws java.io.IOException { return PARSER.parseDelimitedFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseDelimitedFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static Builder newBuilder() { return Builder.create(); } public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder(com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq prototype) { return newBuilder().mergeFrom(prototype); } public Builder toBuilder() { return newBuilder(this); } @java.lang.Override protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code netty.SubscribeReq} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:netty.SubscribeReq) com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReqOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.internal_static_netty_SubscribeReq_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.internal_static_netty_SubscribeReq_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.class, com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.Builder.class); } // Construct using // com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { } } private static Builder create() { return new Builder(); } public Builder clear() { super.clear(); subReqID_ = 0; bitField0_ = (bitField0_ & ~0x00000001); userName_ = ""; bitField0_ = (bitField0_ & ~0x00000002); productName_ = ""; bitField0_ = (bitField0_ & ~0x00000004); address_ = com.google.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); return this; } public Builder clone() { return create().mergeFrom(buildPartial()); } public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.internal_static_netty_SubscribeReq_descriptor; } public com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq getDefaultInstanceForType() { return com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.getDefaultInstance(); } public com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq build() { com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } public com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq buildPartial() { com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq result = new com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq( this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } result.subReqID_ = subReqID_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } result.userName_ = userName_; if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } result.productName_ = productName_; if (((bitField0_ & 0x00000008) == 0x00000008)) { address_ = address_.getUnmodifiableView(); bitField0_ = (bitField0_ & ~0x00000008); } result.address_ = address_; result.bitField0_ = to_bitField0_; onBuilt(); return result; } public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq) { return mergeFrom((com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq) other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq other) { if (other == com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq.getDefaultInstance()) return this; if (other.hasSubReqID()) { setSubReqID(other.getSubReqID()); } if (other.hasUserName()) { bitField0_ |= 0x00000002; userName_ = other.userName_; onChanged(); } if (other.hasProductName()) { bitField0_ |= 0x00000004; productName_ = other.productName_; onChanged(); } if (!other.address_.isEmpty()) { if (address_.isEmpty()) { address_ = other.address_; bitField0_ = (bitField0_ & ~0x00000008); } else { ensureAddressIsMutable(); address_.addAll(other.address_); } onChanged(); } this.mergeUnknownFields(other.getUnknownFields()); return this; } public final boolean isInitialized() { if (!hasSubReqID()) { return false; } if (!hasUserName()) { return false; } if (!hasProductName()) { return false; } return true; } public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (com.lyncc.netty.codec.protobuf.SubscribeReqProto.SubscribeReq) e .getUnfinishedMessage(); throw e; } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private int bitField0_; private int subReqID_; /** * required int32 subReqID = 1; */ public boolean hasSubReqID() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 subReqID = 1; */ public int getSubReqID() { return subReqID_; } /** * required int32 subReqID = 1; */ public Builder setSubReqID(int value) { bitField0_ |= 0x00000001; subReqID_ = value; onChanged(); return this; } /** * required int32 subReqID = 1; */ public Builder clearSubReqID() { bitField0_ = (bitField0_ & ~0x00000001); subReqID_ = 0; onChanged(); return this; } private java.lang.Object userName_ = ""; /** * required string userName = 2; */ public boolean hasUserName() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required string userName = 2; */ public java.lang.String getUserName() { java.lang.Object ref = userName_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { userName_ = s; } return s; } else { return (java.lang.String) ref; } } /** * required string userName = 2; */ public com.google.protobuf.ByteString getUserNameBytes() { java.lang.Object ref = userName_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); userName_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * required string userName = 2; */ public Builder setUserName(java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; userName_ = value; onChanged(); return this; } /** * required string userName = 2; */ public Builder clearUserName() { bitField0_ = (bitField0_ & ~0x00000002); userName_ = getDefaultInstance().getUserName(); onChanged(); return this; } /** * required string userName = 2; */ public Builder setUserNameBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; userName_ = value; onChanged(); return this; } private java.lang.Object productName_ = ""; /** * required string productName = 3; */ public boolean hasProductName() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * required string productName = 3; */ public java.lang.String getProductName() { java.lang.Object ref = productName_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { productName_ = s; } return s; } else { return (java.lang.String) ref; } } /** * required string productName = 3; */ public com.google.protobuf.ByteString getProductNameBytes() { java.lang.Object ref = productName_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); productName_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * required string productName = 3; */ public Builder setProductName(java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; productName_ = value; onChanged(); return this; } /** * required string productName = 3; */ public Builder clearProductName() { bitField0_ = (bitField0_ & ~0x00000004); productName_ = getDefaultInstance().getProductName(); onChanged(); return this; } /** * required string productName = 3; */ public Builder setProductNameBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; productName_ = value; onChanged(); return this; } private com.google.protobuf.LazyStringList address_ = com.google.protobuf.LazyStringArrayList.EMPTY; private void ensureAddressIsMutable() { if (!((bitField0_ & 0x00000008) == 0x00000008)) { address_ = new com.google.protobuf.LazyStringArrayList(address_); bitField0_ |= 0x00000008; } } /** * repeated string address = 4; */ public com.google.protobuf.ProtocolStringList getAddressList() { return address_.getUnmodifiableView(); } /** * repeated string address = 4; */ public int getAddressCount() { return address_.size(); } /** * repeated string address = 4; */ public java.lang.String getAddress(int index) { return address_.get(index); } /** * repeated string address = 4; */ public com.google.protobuf.ByteString getAddressBytes(int index) { return address_.getByteString(index); } /** * repeated string address = 4; */ public Builder setAddress(int index, java.lang.String value) { if (value == null) { throw new NullPointerException(); } ensureAddressIsMutable(); address_.set(index, value); onChanged(); return this; } /** * repeated string address = 4; */ public Builder addAddress(java.lang.String value) { if (value == null) { throw new NullPointerException(); } ensureAddressIsMutable(); address_.add(value); onChanged(); return this; } /** * repeated string address = 4; */ public Builder addAllAddress(java.lang.Iterable values) { ensureAddressIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll(values, address_); onChanged(); return this; } /** * repeated string address = 4; */ public Builder clearAddress() { address_ = com.google.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); onChanged(); return this; } /** * repeated string address = 4; */ public Builder addAddressBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } ensureAddressIsMutable(); address_.add(value); onChanged(); return this; } // @@protoc_insertion_point(builder_scope:netty.SubscribeReq) } static { defaultInstance = new SubscribeReq(true); defaultInstance.initFields(); } // @@protoc_insertion_point(class_scope:netty.SubscribeReq) } private static final com.google.protobuf.Descriptors.Descriptor internal_static_netty_SubscribeReq_descriptor; private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_netty_SubscribeReq_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } private static com.google.protobuf.Descriptors.FileDescriptor descriptor; static { java.lang.String[] descriptorData = { "\n\022SubscribeReq.proto\022\005netty\"X\n\014Subscribe" + "Req\022\020\n\010subReqID\030\001 \002(\005\022\020\n\010userName\030\002 \002(\t\022" + "\023\n\013productName\030\003 \002(\t\022\017\n\007address\030\004 \003(\tB3\n" + "\036com.lyncc.netty.codec.protobufB\021Subscri" + "beReqProto" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); internal_static_netty_SubscribeReq_descriptor = getDescriptor().getMessageTypes().get(0); internal_static_netty_SubscribeReq_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_netty_SubscribeReq_descriptor, new java.lang.String[] { "SubReqID", "UserName", "ProductName", "Address", }); } // @@protoc_insertion_point(outer_class_scope) } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubscribeResp.proto ================================================ package netty; option java_package = "com.lyncc.netty.codec.protobuf"; option java_outer_classname = "SubscribeRespProto"; message SubscribeReq{ required int32 subReqID = 1; required int23 respCode = 2; required string desc = 3; } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/SubscribeRespProto.java ================================================ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: SubscribeResp.proto package com.lyncc.netty.codec.protobuf; public final class SubscribeRespProto { private SubscribeRespProto() {} public static void registerAllExtensions( com.google.protobuf.ExtensionRegistry registry) { } public interface SubscribeRespOrBuilder extends // @@protoc_insertion_point(interface_extends:netty.SubscribeResp) com.google.protobuf.MessageOrBuilder { /** * required int32 subReqID = 1; */ boolean hasSubReqID(); /** * required int32 subReqID = 1; */ int getSubReqID(); /** * required int32 respCode = 2; */ boolean hasRespCode(); /** * required int32 respCode = 2; */ int getRespCode(); /** * required string desc = 3; */ boolean hasDesc(); /** * required string desc = 3; */ java.lang.String getDesc(); /** * required string desc = 3; */ com.google.protobuf.ByteString getDescBytes(); } /** * Protobuf type {@code netty.SubscribeResp} */ public static final class SubscribeResp extends com.google.protobuf.GeneratedMessage implements // @@protoc_insertion_point(message_implements:netty.SubscribeResp) SubscribeRespOrBuilder { // Use SubscribeResp.newBuilder() to construct. private SubscribeResp(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); this.unknownFields = builder.getUnknownFields(); } private SubscribeResp(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } private static final SubscribeResp defaultInstance; public static SubscribeResp getDefaultInstance() { return defaultInstance; } public SubscribeResp getDefaultInstanceForType() { return defaultInstance; } private final com.google.protobuf.UnknownFieldSet unknownFields; @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private SubscribeResp( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { initFields(); int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; default: { if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { done = true; } break; } case 8: { bitField0_ |= 0x00000001; subReqID_ = input.readInt32(); break; } case 16: { bitField0_ |= 0x00000002; respCode_ = input.readInt32(); break; } case 26: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000004; desc_ = bs; break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e.getMessage()).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.internal_static_netty_SubscribeResp_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.internal_static_netty_SubscribeResp_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.class, com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.Builder.class); } public static com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { public SubscribeResp parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new SubscribeResp(input, extensionRegistry); } }; @java.lang.Override public com.google.protobuf.Parser getParserForType() { return PARSER; } private int bitField0_; public static final int SUBREQID_FIELD_NUMBER = 1; private int subReqID_; /** * required int32 subReqID = 1; */ public boolean hasSubReqID() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 subReqID = 1; */ public int getSubReqID() { return subReqID_; } public static final int RESPCODE_FIELD_NUMBER = 2; private int respCode_; /** * required int32 respCode = 2; */ public boolean hasRespCode() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required int32 respCode = 2; */ public int getRespCode() { return respCode_; } public static final int DESC_FIELD_NUMBER = 3; private java.lang.Object desc_; /** * required string desc = 3; */ public boolean hasDesc() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * required string desc = 3; */ public java.lang.String getDesc() { java.lang.Object ref = desc_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { desc_ = s; } return s; } } /** * required string desc = 3; */ public com.google.protobuf.ByteString getDescBytes() { java.lang.Object ref = desc_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); desc_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } private void initFields() { subReqID_ = 0; respCode_ = 0; desc_ = ""; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; if (!hasSubReqID()) { memoizedIsInitialized = 0; return false; } if (!hasRespCode()) { memoizedIsInitialized = 0; return false; } if (!hasDesc()) { memoizedIsInitialized = 0; return false; } memoizedIsInitialized = 1; return true; } public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeInt32(1, subReqID_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeInt32(2, respCode_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { output.writeBytes(3, getDescBytes()); } getUnknownFields().writeTo(output); } private int memoizedSerializedSize = -1; public int getSerializedSize() { int size = memoizedSerializedSize; if (size != -1) return size; size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream .computeInt32Size(1, subReqID_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream .computeInt32Size(2, respCode_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream .computeBytesSize(3, getDescBytes()); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; } private static final long serialVersionUID = 0L; @java.lang.Override protected java.lang.Object writeReplace() throws java.io.ObjectStreamException { return super.writeReplace(); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom(java.io.InputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return PARSER.parseDelimitedFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseDelimitedFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static Builder newBuilder() { return Builder.create(); } public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder(com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp prototype) { return newBuilder().mergeFrom(prototype); } public Builder toBuilder() { return newBuilder(this); } @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessage.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code netty.SubscribeResp} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:netty.SubscribeResp) com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeRespOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.internal_static_netty_SubscribeResp_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.internal_static_netty_SubscribeResp_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.class, com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.Builder.class); } // Construct using com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder( com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { } } private static Builder create() { return new Builder(); } public Builder clear() { super.clear(); subReqID_ = 0; bitField0_ = (bitField0_ & ~0x00000001); respCode_ = 0; bitField0_ = (bitField0_ & ~0x00000002); desc_ = ""; bitField0_ = (bitField0_ & ~0x00000004); return this; } public Builder clone() { return create().mergeFrom(buildPartial()); } public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.internal_static_netty_SubscribeResp_descriptor; } public com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp getDefaultInstanceForType() { return com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.getDefaultInstance(); } public com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp build() { com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } public com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp buildPartial() { com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp result = new com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } result.subReqID_ = subReqID_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } result.respCode_ = respCode_; if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } result.desc_ = desc_; result.bitField0_ = to_bitField0_; onBuilt(); return result; } public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp) { return mergeFrom((com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp)other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp other) { if (other == com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp.getDefaultInstance()) return this; if (other.hasSubReqID()) { setSubReqID(other.getSubReqID()); } if (other.hasRespCode()) { setRespCode(other.getRespCode()); } if (other.hasDesc()) { bitField0_ |= 0x00000004; desc_ = other.desc_; onChanged(); } this.mergeUnknownFields(other.getUnknownFields()); return this; } public final boolean isInitialized() { if (!hasSubReqID()) { return false; } if (!hasRespCode()) { return false; } if (!hasDesc()) { return false; } return true; } public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (com.lyncc.netty.codec.protobuf.SubscribeRespProto.SubscribeResp) e.getUnfinishedMessage(); throw e; } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private int bitField0_; private int subReqID_ ; /** * required int32 subReqID = 1; */ public boolean hasSubReqID() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 subReqID = 1; */ public int getSubReqID() { return subReqID_; } /** * required int32 subReqID = 1; */ public Builder setSubReqID(int value) { bitField0_ |= 0x00000001; subReqID_ = value; onChanged(); return this; } /** * required int32 subReqID = 1; */ public Builder clearSubReqID() { bitField0_ = (bitField0_ & ~0x00000001); subReqID_ = 0; onChanged(); return this; } private int respCode_ ; /** * required int32 respCode = 2; */ public boolean hasRespCode() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required int32 respCode = 2; */ public int getRespCode() { return respCode_; } /** * required int32 respCode = 2; */ public Builder setRespCode(int value) { bitField0_ |= 0x00000002; respCode_ = value; onChanged(); return this; } /** * required int32 respCode = 2; */ public Builder clearRespCode() { bitField0_ = (bitField0_ & ~0x00000002); respCode_ = 0; onChanged(); return this; } private java.lang.Object desc_ = ""; /** * required string desc = 3; */ public boolean hasDesc() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * required string desc = 3; */ public java.lang.String getDesc() { java.lang.Object ref = desc_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { desc_ = s; } return s; } else { return (java.lang.String) ref; } } /** * required string desc = 3; */ public com.google.protobuf.ByteString getDescBytes() { java.lang.Object ref = desc_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); desc_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * required string desc = 3; */ public Builder setDesc( java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; desc_ = value; onChanged(); return this; } /** * required string desc = 3; */ public Builder clearDesc() { bitField0_ = (bitField0_ & ~0x00000004); desc_ = getDefaultInstance().getDesc(); onChanged(); return this; } /** * required string desc = 3; */ public Builder setDescBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; desc_ = value; onChanged(); return this; } // @@protoc_insertion_point(builder_scope:netty.SubscribeResp) } static { defaultInstance = new SubscribeResp(true); defaultInstance.initFields(); } // @@protoc_insertion_point(class_scope:netty.SubscribeResp) } private static final com.google.protobuf.Descriptors.Descriptor internal_static_netty_SubscribeResp_descriptor; private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_netty_SubscribeResp_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } private static com.google.protobuf.Descriptors.FileDescriptor descriptor; static { java.lang.String[] descriptorData = { "\n\023SubscribeResp.proto\022\005netty\"A\n\rSubscrib" + "eResp\022\020\n\010subReqID\030\001 \002(\005\022\020\n\010respCode\030\002 \002(" + "\005\022\014\n\004desc\030\003 \002(\tB4\n\036com.lyncc.netty.codec" + ".protobufB\022SubscribeRespProto" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] { }, assigner); internal_static_netty_SubscribeResp_descriptor = getDescriptor().getMessageTypes().get(0); internal_static_netty_SubscribeResp_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_netty_SubscribeResp_descriptor, new java.lang.String[] { "SubReqID", "RespCode", "Desc", }); } // @@protoc_insertion_point(outer_class_scope) } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/TestSubscribeReqProto.java ================================================ package com.lyncc.netty.codec.protobuf; import java.util.ArrayList; import java.util.List; import com.google.protobuf.InvalidProtocolBufferException; public class TestSubscribeReqProto { private static byte[] encode(SubscribeReqProto.SubscribeReq req) { return req.toByteArray(); } private static SubscribeReqProto.SubscribeReq decode(byte[] body) throws InvalidProtocolBufferException { return SubscribeReqProto.SubscribeReq.parseFrom(body); } private static SubscribeReqProto.SubscribeReq createSubscribeReq() { SubscribeReqProto.SubscribeReq.Builder builder = SubscribeReqProto.SubscribeReq.newBuilder(); builder.setSubReqID(1); builder.setUserName("Lilinfeng"); builder.setProductName("Netty Book"); List address = new ArrayList(); address.add("NanJing YuHuaTai"); address.add("BeiJing LiuLiChang"); address.add("ShenZhen HongShuLin"); builder.addAllAddress(address); return builder.build(); } /** * @param args * @throws InvalidProtocolBufferException */ public static void main(String[] args) throws InvalidProtocolBufferException { SubscribeReqProto.SubscribeReq req = createSubscribeReq(); System.out.println("Before encode : " + req.toString()); SubscribeReqProto.SubscribeReq req2 = decode(encode(req)); System.out.println("After decode : " + req.toString()); System.out.println("Assert equal : --> " + req2.equals(req)); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/ProtoBufClient.java ================================================ package com.lyncc.netty.codec.protobuf.demo; import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; public class ProtoBufClient { public void connect(int port, String host) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); ch.pipeline().addLast(new ProtobufEncoder()); ch.pipeline().addLast(new ProtoBufClientHandler()); } }); ChannelFuture f = b.connect(host, port).sync(); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new ProtoBufClient().connect(port, "127.0.0.1"); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/ProtoBufClientHandler.java ================================================ package com.lyncc.netty.codec.protobuf.demo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.ArrayList; import java.util.List; import com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car; import com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType; public class ProtoBufClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("======================================="); RichManProto.RichMan.Builder builder = RichManProto.RichMan.newBuilder(); builder.setName("王思聪"); builder.setId(1); builder.setEmail("wsc@163.com"); List cars = new ArrayList(); Car car1 = RichManProto.RichMan.Car.newBuilder().setName("上海大众超跑").setType(CarType.DASAUTO).build(); Car car2 = RichManProto.RichMan.Car.newBuilder().setName("Aventador").setType(CarType.LAMBORGHINI).build(); Car car3 = RichManProto.RichMan.Car.newBuilder().setName("奔驰SLS级AMG").setType(CarType.BENZ).build(); cars.add(car1); cars.add(car2); cars.add(car3); builder.addAllCars(cars); ctx.writeAndFlush(builder.build()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/ProtoBufServer.java ================================================ package com.lyncc.netty.codec.protobuf.demo; 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.ProtobufVarint32FrameDecoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public class ProtoBufServer { public void bind(int port) throws Exception { // 配置服务端的NIO线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); ch.pipeline().addLast(new ProtobufDecoder(RichManProto.RichMan.getDefaultInstance())); ch.pipeline().addLast(new ProtoBufServerHandler()); } }); // 绑定端口,同步等待成功 ChannelFuture f = b.bind(port).sync(); System.out.println("init start"); // 等待服务端监听端口关闭 f.channel().closeFuture().sync(); } finally { // 优雅退出,释放线程池资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new ProtoBufServer().bind(port); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/ProtoBufServerHandler.java ================================================ package com.lyncc.netty.codec.protobuf.demo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.List; import com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car; public class ProtoBufServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { RichManProto.RichMan req = (RichManProto.RichMan) msg; System.out.println(req.getName()+"他有"+req.getCarsCount()+"量车"); List lists = req.getCarsList(); if(null != lists) { for(Car car : lists){ System.out.println(car.getName()); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/RichMan.proto ================================================ package netty; option java_package = "com.lyncc.netty.codec.protobuf.demo"; option java_outer_classname = "RichManProto"; message RichMan { required int32 id = 1; required string name = 2; optional string email = 3; enum CarType { AUDI = 0; BENZ = 1; LAMBORGHINI = 2; DASAUTO = 3; } message Car { required string name = 1; optional CarType type = 2 [default = BENZ]; } repeated Car cars = 4; } ================================================ FILE: src/main/java/com/lyncc/netty/codec/protobuf/demo/RichManProto.java ================================================ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: RichMan.proto package com.lyncc.netty.codec.protobuf.demo; public final class RichManProto { private RichManProto() { } public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { } public interface RichManOrBuilder extends // @@protoc_insertion_point(interface_extends:netty.RichMan) com.google.protobuf.MessageOrBuilder { /** * required int32 id = 1; */ boolean hasId(); /** * required int32 id = 1; */ int getId(); /** * required string name = 2; */ boolean hasName(); /** * required string name = 2; */ java.lang.String getName(); /** * required string name = 2; */ com.google.protobuf.ByteString getNameBytes(); /** * optional string email = 3; */ boolean hasEmail(); /** * optional string email = 3; */ java.lang.String getEmail(); /** * optional string email = 3; */ com.google.protobuf.ByteString getEmailBytes(); /** * repeated .netty.RichMan.Car cars = 4; */ java.util.List getCarsList(); /** * repeated .netty.RichMan.Car cars = 4; */ com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car getCars(int index); /** * repeated .netty.RichMan.Car cars = 4; */ int getCarsCount(); /** * repeated .netty.RichMan.Car cars = 4; */ java.util.List getCarsOrBuilderList(); /** * repeated .netty.RichMan.Car cars = 4; */ com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarOrBuilder getCarsOrBuilder(int index); } /** * Protobuf type {@code netty.RichMan} */ public static final class RichMan extends com.google.protobuf.GeneratedMessage implements // @@protoc_insertion_point(message_implements:netty.RichMan) RichManOrBuilder { // Use RichMan.newBuilder() to construct. private RichMan(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); this.unknownFields = builder.getUnknownFields(); } private RichMan(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } private static final RichMan defaultInstance; public static RichMan getDefaultInstance() { return defaultInstance; } public RichMan getDefaultInstanceForType() { return defaultInstance; } private final com.google.protobuf.UnknownFieldSet unknownFields; @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private RichMan(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { initFields(); int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet .newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; default: { if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { done = true; } break; } case 8: { bitField0_ |= 0x00000001; id_ = input.readInt32(); break; } case 18: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000002; name_ = bs; break; } case 26: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000004; email_ = bs; break; } case 34: { if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { cars_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000008; } cars_.add(input.readMessage( com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.PARSER, extensionRegistry)); break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { cars_ = java.util.Collections.unmodifiableList(cars_); } this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_fieldAccessorTable .ensureFieldAccessorsInitialized(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.class, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Builder.class); } public static com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { public RichMan parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new RichMan(input, extensionRegistry); } }; @java.lang.Override public com.google.protobuf.Parser getParserForType() { return PARSER; } /** * Protobuf enum {@code netty.RichMan.CarType} */ public enum CarType implements com.google.protobuf.ProtocolMessageEnum { /** * AUDI = 0; */ AUDI(0, 0), /** * BENZ = 1; */ BENZ(1, 1), /** * LAMBORGHINI = 2; */ LAMBORGHINI(2, 2), /** * DASAUTO = 3; */ DASAUTO(3, 3), ; /** * AUDI = 0; */ public static final int AUDI_VALUE = 0; /** * BENZ = 1; */ public static final int BENZ_VALUE = 1; /** * LAMBORGHINI = 2; */ public static final int LAMBORGHINI_VALUE = 2; /** * DASAUTO = 3; */ public static final int DASAUTO_VALUE = 3; public final int getNumber() { return value; } public static CarType valueOf(int value) { switch (value) { case 0: return AUDI; case 1: return BENZ; case 2: return LAMBORGHINI; case 3: return DASAUTO; default: return null; } } public static com.google.protobuf.Internal.EnumLiteMap internalGetValueMap() { return internalValueMap; } private static com.google.protobuf.Internal.EnumLiteMap internalValueMap = new com.google.protobuf.Internal.EnumLiteMap() { public CarType findValueByNumber(int number) { return CarType.valueOf(number); } }; public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() { return getDescriptor().getValues().get(index); } public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() { return getDescriptor(); } public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.getDescriptor().getEnumTypes().get(0); } private static final CarType[] VALUES = values(); public static CarType valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) { if (desc.getType() != getDescriptor()) { throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type."); } return VALUES[desc.getIndex()]; } private final int index; private final int value; private CarType(int index, int value) { this.index = index; this.value = value; } // @@protoc_insertion_point(enum_scope:netty.RichMan.CarType) } public interface CarOrBuilder extends // @@protoc_insertion_point(interface_extends:netty.RichMan.Car) com.google.protobuf.MessageOrBuilder { /** * required string name = 1; */ boolean hasName(); /** * required string name = 1; */ java.lang.String getName(); /** * required string name = 1; */ com.google.protobuf.ByteString getNameBytes(); /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ boolean hasType(); /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType getType(); } /** * Protobuf type {@code netty.RichMan.Car} */ public static final class Car extends com.google.protobuf.GeneratedMessage implements // @@protoc_insertion_point(message_implements:netty.RichMan.Car) CarOrBuilder { // Use Car.newBuilder() to construct. private Car(com.google.protobuf.GeneratedMessage.Builder builder) { super(builder); this.unknownFields = builder.getUnknownFields(); } private Car(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } private static final Car defaultInstance; public static Car getDefaultInstance() { return defaultInstance; } public Car getDefaultInstanceForType() { return defaultInstance; } private final com.google.protobuf.UnknownFieldSet unknownFields; @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private Car(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { initFields(); int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet .newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; default: { if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { done = true; } break; } case 10: { com.google.protobuf.ByteString bs = input.readBytes(); bitField0_ |= 0x00000001; name_ = bs; break; } case 16: { int rawValue = input.readEnum(); com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType value = com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType .valueOf(rawValue); if (value == null) { unknownFields.mergeVarintField(2, rawValue); } else { bitField0_ |= 0x00000002; type_ = value; } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException(e.getMessage()) .setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_Car_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_Car_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.class, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder.class); } public static com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { public Car parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new Car(input, extensionRegistry); } }; @java.lang.Override public com.google.protobuf.Parser getParserForType() { return PARSER; } private int bitField0_; public static final int NAME_FIELD_NUMBER = 1; private java.lang.Object name_; /** * required string name = 1; */ public boolean hasName() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required string name = 1; */ public java.lang.String getName() { java.lang.Object ref = name_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { name_ = s; } return s; } } /** * required string name = 1; */ public com.google.protobuf.ByteString getNameBytes() { java.lang.Object ref = name_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); name_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } public static final int TYPE_FIELD_NUMBER = 2; private com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType type_; /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public boolean hasType() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType getType() { return type_; } private void initFields() { name_ = ""; type_ = com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType.BENZ; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; if (!hasName()) { memoizedIsInitialized = 0; return false; } memoizedIsInitialized = 1; return true; } public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeBytes(1, getNameBytes()); } if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeEnum(2, type_.getNumber()); } getUnknownFields().writeTo(output); } private int memoizedSerializedSize = -1; public int getSerializedSize() { int size = memoizedSerializedSize; if (size != -1) return size; size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream.computeBytesSize(1, getNameBytes()); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream.computeEnumSize(2, type_.getNumber()); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; } private static final long serialVersionUID = 0L; @java.lang.Override protected java.lang.Object writeReplace() throws java.io.ObjectStreamException { return super.writeReplace(); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( java.io.InputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseDelimitedFrom( java.io.InputStream input) throws java.io.IOException { return PARSER.parseDelimitedFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseDelimitedFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static Builder newBuilder() { return Builder.create(); } public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car prototype) { return newBuilder().mergeFrom(prototype); } public Builder toBuilder() { return newBuilder(this); } @java.lang.Override protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code netty.RichMan.Car} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:netty.RichMan.Car) com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_Car_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_Car_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.class, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder.class); } // Construct using // com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { } } private static Builder create() { return new Builder(); } public Builder clear() { super.clear(); name_ = ""; bitField0_ = (bitField0_ & ~0x00000001); type_ = com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType.BENZ; bitField0_ = (bitField0_ & ~0x00000002); return this; } public Builder clone() { return create().mergeFrom(buildPartial()); } public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_Car_descriptor; } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car getDefaultInstanceForType() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.getDefaultInstance(); } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car build() { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car buildPartial() { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car result = new com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car( this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } result.name_ = name_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } result.type_ = type_; result.bitField0_ = to_bitField0_; onBuilt(); return result; } public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car) { return mergeFrom((com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car) other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car other) { if (other == com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.getDefaultInstance()) return this; if (other.hasName()) { bitField0_ |= 0x00000001; name_ = other.name_; onChanged(); } if (other.hasType()) { setType(other.getType()); } this.mergeUnknownFields(other.getUnknownFields()); return this; } public final boolean isInitialized() { if (!hasName()) { return false; } return true; } public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car) e .getUnfinishedMessage(); throw e; } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private int bitField0_; private java.lang.Object name_ = ""; /** * required string name = 1; */ public boolean hasName() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required string name = 1; */ public java.lang.String getName() { java.lang.Object ref = name_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { name_ = s; } return s; } else { return (java.lang.String) ref; } } /** * required string name = 1; */ public com.google.protobuf.ByteString getNameBytes() { java.lang.Object ref = name_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); name_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * required string name = 1; */ public Builder setName(java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000001; name_ = value; onChanged(); return this; } /** * required string name = 1; */ public Builder clearName() { bitField0_ = (bitField0_ & ~0x00000001); name_ = getDefaultInstance().getName(); onChanged(); return this; } /** * required string name = 1; */ public Builder setNameBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000001; name_ = value; onChanged(); return this; } private com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType type_ = com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType.BENZ; /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public boolean hasType() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType getType() { return type_; } /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public Builder setType(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; type_ = value; onChanged(); return this; } /** * optional .netty.RichMan.CarType type = 2 [default = BENZ]; */ public Builder clearType() { bitField0_ = (bitField0_ & ~0x00000002); type_ = com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarType.BENZ; onChanged(); return this; } // @@protoc_insertion_point(builder_scope:netty.RichMan.Car) } static { defaultInstance = new Car(true); defaultInstance.initFields(); } // @@protoc_insertion_point(class_scope:netty.RichMan.Car) } private int bitField0_; public static final int ID_FIELD_NUMBER = 1; private int id_; /** * required int32 id = 1; */ public boolean hasId() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 id = 1; */ public int getId() { return id_; } public static final int NAME_FIELD_NUMBER = 2; private java.lang.Object name_; /** * required string name = 2; */ public boolean hasName() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required string name = 2; */ public java.lang.String getName() { java.lang.Object ref = name_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { name_ = s; } return s; } } /** * required string name = 2; */ public com.google.protobuf.ByteString getNameBytes() { java.lang.Object ref = name_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); name_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } public static final int EMAIL_FIELD_NUMBER = 3; private java.lang.Object email_; /** * optional string email = 3; */ public boolean hasEmail() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * optional string email = 3; */ public java.lang.String getEmail() { java.lang.Object ref = email_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { email_ = s; } return s; } } /** * optional string email = 3; */ public com.google.protobuf.ByteString getEmailBytes() { java.lang.Object ref = email_; if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); email_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } public static final int CARS_FIELD_NUMBER = 4; private java.util.List cars_; /** * repeated .netty.RichMan.Car cars = 4; */ public java.util.List getCarsList() { return cars_; } /** * repeated .netty.RichMan.Car cars = 4; */ public java.util.List getCarsOrBuilderList() { return cars_; } /** * repeated .netty.RichMan.Car cars = 4; */ public int getCarsCount() { return cars_.size(); } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car getCars(int index) { return cars_.get(index); } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarOrBuilder getCarsOrBuilder(int index) { return cars_.get(index); } private void initFields() { id_ = 0; name_ = ""; email_ = ""; cars_ = java.util.Collections.emptyList(); } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; if (!hasId()) { memoizedIsInitialized = 0; return false; } if (!hasName()) { memoizedIsInitialized = 0; return false; } for (int i = 0; i < getCarsCount(); i++) { if (!getCars(i).isInitialized()) { memoizedIsInitialized = 0; return false; } } memoizedIsInitialized = 1; return true; } public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeInt32(1, id_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeBytes(2, getNameBytes()); } if (((bitField0_ & 0x00000004) == 0x00000004)) { output.writeBytes(3, getEmailBytes()); } for (int i = 0; i < cars_.size(); i++) { output.writeMessage(4, cars_.get(i)); } getUnknownFields().writeTo(output); } private int memoizedSerializedSize = -1; public int getSerializedSize() { int size = memoizedSerializedSize; if (size != -1) return size; size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, id_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream.computeBytesSize(2, getNameBytes()); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream.computeBytesSize(3, getEmailBytes()); } for (int i = 0; i < cars_.size(); i++) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(4, cars_.get(i)); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; } private static final long serialVersionUID = 0L; @java.lang.Override protected java.lang.Object writeReplace() throws java.io.ObjectStreamException { return super.writeReplace(); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom(java.io.InputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseDelimitedFrom( java.io.InputStream input) throws java.io.IOException { return PARSER.parseDelimitedFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseDelimitedFrom(input, extensionRegistry); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return PARSER.parseFrom(input); } public static com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return PARSER.parseFrom(input, extensionRegistry); } public static Builder newBuilder() { return Builder.create(); } public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan prototype) { return newBuilder().mergeFrom(prototype); } public Builder toBuilder() { return newBuilder(this); } @java.lang.Override protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code netty.RichMan} */ public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements // @@protoc_insertion_point(builder_implements:netty.RichMan) com.lyncc.netty.codec.protobuf.demo.RichManProto.RichManOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_fieldAccessorTable .ensureFieldAccessorsInitialized( com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.class, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Builder.class); } // Construct using // com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { getCarsFieldBuilder(); } } private static Builder create() { return new Builder(); } public Builder clear() { super.clear(); id_ = 0; bitField0_ = (bitField0_ & ~0x00000001); name_ = ""; bitField0_ = (bitField0_ & ~0x00000002); email_ = ""; bitField0_ = (bitField0_ & ~0x00000004); if (carsBuilder_ == null) { cars_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000008); } else { carsBuilder_.clear(); } return this; } public Builder clone() { return create().mergeFrom(buildPartial()); } public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.internal_static_netty_RichMan_descriptor; } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan getDefaultInstanceForType() { return com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.getDefaultInstance(); } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan build() { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan buildPartial() { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan result = new com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan( this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } result.id_ = id_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } result.name_ = name_; if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } result.email_ = email_; if (carsBuilder_ == null) { if (((bitField0_ & 0x00000008) == 0x00000008)) { cars_ = java.util.Collections.unmodifiableList(cars_); bitField0_ = (bitField0_ & ~0x00000008); } result.cars_ = cars_; } else { result.cars_ = carsBuilder_.build(); } result.bitField0_ = to_bitField0_; onBuilt(); return result; } public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan) { return mergeFrom((com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan) other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan other) { if (other == com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.getDefaultInstance()) return this; if (other.hasId()) { setId(other.getId()); } if (other.hasName()) { bitField0_ |= 0x00000002; name_ = other.name_; onChanged(); } if (other.hasEmail()) { bitField0_ |= 0x00000004; email_ = other.email_; onChanged(); } if (carsBuilder_ == null) { if (!other.cars_.isEmpty()) { if (cars_.isEmpty()) { cars_ = other.cars_; bitField0_ = (bitField0_ & ~0x00000008); } else { ensureCarsIsMutable(); cars_.addAll(other.cars_); } onChanged(); } } else { if (!other.cars_.isEmpty()) { if (carsBuilder_.isEmpty()) { carsBuilder_.dispose(); carsBuilder_ = null; cars_ = other.cars_; bitField0_ = (bitField0_ & ~0x00000008); carsBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? getCarsFieldBuilder() : null; } else { carsBuilder_.addAllMessages(other.cars_); } } } this.mergeUnknownFields(other.getUnknownFields()); return this; } public final boolean isInitialized() { if (!hasId()) { return false; } if (!hasName()) { return false; } for (int i = 0; i < getCarsCount(); i++) { if (!getCars(i).isInitialized()) { return false; } } return true; } public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan) e.getUnfinishedMessage(); throw e; } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private int bitField0_; private int id_; /** * required int32 id = 1; */ public boolean hasId() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** * required int32 id = 1; */ public int getId() { return id_; } /** * required int32 id = 1; */ public Builder setId(int value) { bitField0_ |= 0x00000001; id_ = value; onChanged(); return this; } /** * required int32 id = 1; */ public Builder clearId() { bitField0_ = (bitField0_ & ~0x00000001); id_ = 0; onChanged(); return this; } private java.lang.Object name_ = ""; /** * required string name = 2; */ public boolean hasName() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** * required string name = 2; */ public java.lang.String getName() { java.lang.Object ref = name_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { name_ = s; } return s; } else { return (java.lang.String) ref; } } /** * required string name = 2; */ public com.google.protobuf.ByteString getNameBytes() { java.lang.Object ref = name_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); name_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * required string name = 2; */ public Builder setName(java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; name_ = value; onChanged(); return this; } /** * required string name = 2; */ public Builder clearName() { bitField0_ = (bitField0_ & ~0x00000002); name_ = getDefaultInstance().getName(); onChanged(); return this; } /** * required string name = 2; */ public Builder setNameBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; name_ = value; onChanged(); return this; } private java.lang.Object email_ = ""; /** * optional string email = 3; */ public boolean hasEmail() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** * optional string email = 3; */ public java.lang.String getEmail() { java.lang.Object ref = email_; if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { email_ = s; } return s; } else { return (java.lang.String) ref; } } /** * optional string email = 3; */ public com.google.protobuf.ByteString getEmailBytes() { java.lang.Object ref = email_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString .copyFromUtf8((java.lang.String) ref); email_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * optional string email = 3; */ public Builder setEmail(java.lang.String value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; email_ = value; onChanged(); return this; } /** * optional string email = 3; */ public Builder clearEmail() { bitField0_ = (bitField0_ & ~0x00000004); email_ = getDefaultInstance().getEmail(); onChanged(); return this; } /** * optional string email = 3; */ public Builder setEmailBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; email_ = value; onChanged(); return this; } private java.util.List cars_ = java.util.Collections .emptyList(); private void ensureCarsIsMutable() { if (!((bitField0_ & 0x00000008) == 0x00000008)) { cars_ = new java.util.ArrayList(cars_); bitField0_ |= 0x00000008; } } private com.google.protobuf.RepeatedFieldBuilder carsBuilder_; /** * repeated .netty.RichMan.Car cars = 4; */ public java.util.List getCarsList() { if (carsBuilder_ == null) { return java.util.Collections.unmodifiableList(cars_); } else { return carsBuilder_.getMessageList(); } } /** * repeated .netty.RichMan.Car cars = 4; */ public int getCarsCount() { if (carsBuilder_ == null) { return cars_.size(); } else { return carsBuilder_.getCount(); } } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car getCars(int index) { if (carsBuilder_ == null) { return cars_.get(index); } else { return carsBuilder_.getMessage(index); } } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder setCars(int index, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car value) { if (carsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } ensureCarsIsMutable(); cars_.set(index, value); onChanged(); } else { carsBuilder_.setMessage(index, value); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder setCars(int index, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder builderForValue) { if (carsBuilder_ == null) { ensureCarsIsMutable(); cars_.set(index, builderForValue.build()); onChanged(); } else { carsBuilder_.setMessage(index, builderForValue.build()); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder addCars(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car value) { if (carsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } ensureCarsIsMutable(); cars_.add(value); onChanged(); } else { carsBuilder_.addMessage(value); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder addCars(int index, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car value) { if (carsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } ensureCarsIsMutable(); cars_.add(index, value); onChanged(); } else { carsBuilder_.addMessage(index, value); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder addCars(com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder builderForValue) { if (carsBuilder_ == null) { ensureCarsIsMutable(); cars_.add(builderForValue.build()); onChanged(); } else { carsBuilder_.addMessage(builderForValue.build()); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder addCars(int index, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder builderForValue) { if (carsBuilder_ == null) { ensureCarsIsMutable(); cars_.add(index, builderForValue.build()); onChanged(); } else { carsBuilder_.addMessage(index, builderForValue.build()); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder addAllCars( java.lang.Iterable values) { if (carsBuilder_ == null) { ensureCarsIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll(values, cars_); onChanged(); } else { carsBuilder_.addAllMessages(values); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder clearCars() { if (carsBuilder_ == null) { cars_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000008); onChanged(); } else { carsBuilder_.clear(); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public Builder removeCars(int index) { if (carsBuilder_ == null) { ensureCarsIsMutable(); cars_.remove(index); onChanged(); } else { carsBuilder_.remove(index); } return this; } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder getCarsBuilder(int index) { return getCarsFieldBuilder().getBuilder(index); } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.CarOrBuilder getCarsOrBuilder(int index) { if (carsBuilder_ == null) { return cars_.get(index); } else { return carsBuilder_.getMessageOrBuilder(index); } } /** * repeated .netty.RichMan.Car cars = 4; */ public java.util.List getCarsOrBuilderList() { if (carsBuilder_ != null) { return carsBuilder_.getMessageOrBuilderList(); } else { return java.util.Collections.unmodifiableList(cars_); } } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder addCarsBuilder() { return getCarsFieldBuilder().addBuilder( com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.getDefaultInstance()); } /** * repeated .netty.RichMan.Car cars = 4; */ public com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.Builder addCarsBuilder(int index) { return getCarsFieldBuilder().addBuilder(index, com.lyncc.netty.codec.protobuf.demo.RichManProto.RichMan.Car.getDefaultInstance()); } /** * repeated .netty.RichMan.Car cars = 4; */ public java.util.List getCarsBuilderList() { return getCarsFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilder getCarsFieldBuilder() { if (carsBuilder_ == null) { carsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder( cars_, ((bitField0_ & 0x00000008) == 0x00000008), getParentForChildren(), isClean()); cars_ = null; } return carsBuilder_; } // @@protoc_insertion_point(builder_scope:netty.RichMan) } static { defaultInstance = new RichMan(true); defaultInstance.initFields(); } // @@protoc_insertion_point(class_scope:netty.RichMan) } private static final com.google.protobuf.Descriptors.Descriptor internal_static_netty_RichMan_descriptor; private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_netty_RichMan_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor internal_static_netty_RichMan_Car_descriptor; private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_netty_RichMan_Car_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } private static com.google.protobuf.Descriptors.FileDescriptor descriptor; static { java.lang.String[] descriptorData = { "\n\rRichMan.proto\022\005netty\"\322\001\n\007RichMan\022\n\n\002id" + "\030\001 \002(\005\022\014\n\004name\030\002 \002(\t\022\r\n\005email\030\003 \001(\t\022 \n\004c" + "ars\030\004 \003(\0132\022.netty.RichMan.Car\032?\n\003Car\022\014\n\004" + "name\030\001 \002(\t\022*\n\004type\030\002 \001(\0162\026.netty.RichMan" + ".CarType:\004BENZ\";\n\007CarType\022\010\n\004AUDI\020\000\022\010\n\004B" + "ENZ\020\001\022\017\n\013LAMBORGHINI\020\002\022\013\n\007DASAUTO\020\003B3\n#c" + "om.lyncc.netty.codec.protobuf.demoB\014Rich" + "ManProto" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); internal_static_netty_RichMan_descriptor = getDescriptor().getMessageTypes().get(0); internal_static_netty_RichMan_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_netty_RichMan_descriptor, new java.lang.String[] { "Id", "Name", "Email", "Cars", }); internal_static_netty_RichMan_Car_descriptor = internal_static_netty_RichMan_descriptor.getNestedTypes().get(0); internal_static_netty_RichMan_Car_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_netty_RichMan_Car_descriptor, new java.lang.String[] { "Name", "Type", }); } // @@protoc_insertion_point(outer_class_scope) } ================================================ FILE: src/main/java/com/lyncc/netty/component/channelhandler/BaseClient.java ================================================ package com.lyncc.netty.component.channelhandler; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast(new BaseClient1Handler()); p.addLast(new BaseClient2Handler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/component/channelhandler/BaseClient1Handler.java ================================================ package com.lyncc.netty.component.channelhandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * * @author bazingaLyncc * 描述:客户端的第一个自定义的inbound处理器 * 时间 2016年5月3日 */ public class BaseClient1Handler extends ChannelInboundHandlerAdapter{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("BaseClient1Handler channelActive"); ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("BaseClient1Handler channelInactive"); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/channelhandler/BaseClient2Handler.java ================================================ package com.lyncc.netty.component.channelhandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * * @author bazingaLyncc * 描述:客户端的第二个自定义的inbound处理器 * 时间 2016年5月3日 */ public class BaseClient2Handler extends ChannelInboundHandlerAdapter{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("BaseClient2Handler Active"); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/channelhandler/BaseServer.java ================================================ package com.lyncc.netty.component.channelhandler; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { // ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/channelhandler/BaseServerHandler.java ================================================ package com.lyncc.netty.component.channelhandler; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString()); ctx.writeAndFlush(Unpooled.copiedBuffer("hello my name is lyncc", CharsetUtil.UTF_8)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/simplehandler/BaseClient.java ================================================ package com.lyncc.netty.component.simplehandler; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast(new BaseClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/component/simplehandler/BaseClientHandler.java ================================================ package com.lyncc.netty.component.simplehandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class BaseClientHandler extends SimpleChannelInboundHandler{ @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println("Client channelRead0 received:" + msg); } // @Override // public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // System.out.println("Client channelRead received:" + msg); // // } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/simplehandler/BaseServer.java ================================================ package com.lyncc.netty.component.simplehandler; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { // ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/component/simplehandler/BaseServerHandler.java ================================================ package com.lyncc.netty.component.simplehandler; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString()); ctx.writeAndFlush(Unpooled.copiedBuffer("hello my name is lyncc", CharsetUtil.UTF_8)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/concept/HelloWorldConcept.java ================================================ package com.lyncc.netty.concept; /** * * @author Bazingalyncc * 描述: * 时间 2016年4月29日 */ public class HelloWorldConcept { /** * * * * * ________________________ __________________________ * | | | | * | <-----Inbound----- | | ---inbound------- > | ________ * | _____ ______ | | _______ ____ | | | * _______ | | | | | | | | | | | | | | * | | | | ② | | ③ | | ___________________ | | ⑤ | | ⑥ | | | | * | | | |_____| |____| | | | | |_____| |____| | | | * |client |----|-------______-----------|-----| network |-----|--------------------------|--| server | * | | | | | | |___________________| | ______ | | | * | | | | ① | | | | | | | | * | | | |_____| | | | ④ | | |________| * | | | | | |_____| | * |_______| | -----Outbound---> | | <-----outbound---- | * |___ChannelPipeline______| |______ChannelPipeline_____| * * ①:StringEncoder继承于MessageToMessageEncoder,而MessageToMessageEncoder又继承于ChannelOutboundHandlerAdapter * ②:HelloWorldClientHandler.java * ③:StringDecoder继承于MessageToMessageDecoder,而MessageToMessageDecoder又继承于ChannelInboundHandlerAdapter * ④:StringEncoder 编码器 * ⑤:StringDecoder 解码器 * ⑥:HelloWorldServerHandler.java * * * */ } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat/BaseClient.java ================================================ package com.lyncc.netty.heartbeat; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; public class BaseClient { public void connect(int port, String host) throws Exception { ChannelFuture future = null; // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap().group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast("ping", new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS)); p.addLast(new BaseClientHandler()); } }); try { future = b.connect(host, port).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { // group.shutdownGracefully(); if (null != future) { if (future.channel() != null && future.channel().isOpen()) { future.channel().close(); } } System.out.println("准备重连"); connect(port, host); System.out.println("重连成功"); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new BaseClient().connect(port, "127.0.0.1"); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat/BaseClientHandler.java ================================================ package com.lyncc.netty.heartbeat; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; import java.util.Date; /** * * @author bazingaLyncc 描述:客户端的第一个自定义的inbound处理器 时间 2016年5月3日 */ public class BaseClientHandler extends ChannelInboundHandlerAdapter { private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat", CharsetUtil.UTF_8)); private static final int TRY_TIMES = 3; private int currentTime = 0; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("启动时间是:"+new Date()); System.out.println("BaseClient1Handler channelActive"); ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("BaseClient1Handler channelInactive"); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("触发时间:"+new Date()); if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.WRITER_IDLE) { if(currentTime <= TRY_TIMES){ System.out.println("currentTime:"+currentTime); currentTime++; ctx.channel().writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()); } } } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String message = (String) msg; System.out.println(message); if (message.equals("Heartbeat")) { ctx.write("has read message from server"); ctx.flush(); } ReferenceCountUtil.release(msg); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat/BaseServer.java ================================================ package com.lyncc.netty.heartbeat; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.IdleStateHandler; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { private static final int READ_IDEL_TIME_OUT = 5; // 读超时 private static final int WRITE_IDEL_TIME_OUT = 0;// 写超时 private static final int ALL_IDEL_TIME_OUT = 0; // 所有超时 protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS)); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat/BaseServerHandler.java ================================================ package com.lyncc.netty.heartbeat; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ private int loss_connect_time = 0; @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("hehehehe"); if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE) { loss_connect_time++; System.out.println("10 秒没有接收到客户端的信息了"); if(loss_connect_time > 2 ){ ctx.channel().close(); } } } else { super.userEventTriggered(ctx, evt); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/AskMsg.java ================================================ package com.lyncc.netty.heartbeat2; public class AskMsg extends BaseMsg { public AskMsg() { super(); setType(MsgType.ASK); } private AskParams params; public AskParams getParams() { return params; } public void setParams(AskParams params) { this.params = params; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/AskParams.java ================================================ package com.lyncc.netty.heartbeat2; import java.io.Serializable; public class AskParams implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String auth; public String getAuth() { return auth; } public void setAuth(String auth) { this.auth = auth; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/BaseMsg.java ================================================ package com.lyncc.netty.heartbeat2; import java.io.Serializable; public abstract class BaseMsg implements Serializable { /** * */ private static final long serialVersionUID = 1L; private MsgType type; private String clientId; public BaseMsg() { this.clientId = Constants.getClientId(); } public MsgType getType() { return type; } public void setType(MsgType type) { this.type = type; } public String getClientId() { return clientId; } public void setClientId(String clientId) { this.clientId = clientId; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/Constants.java ================================================ package com.lyncc.netty.heartbeat2; public class Constants { private static String clientId; public static String getClientId() { return clientId; } public static void setClientId(String clientId) { Constants.clientId = clientId; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/LoginMsg.java ================================================ package com.lyncc.netty.heartbeat2; public class LoginMsg extends BaseMsg { private String userName; private String password; public LoginMsg() { super(); setType(MsgType.LOGIN); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/MsgType.java ================================================ package com.lyncc.netty.heartbeat2; public enum MsgType { PING,ASK,REPLY,LOGIN } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/NettyChannelMap.java ================================================ package com.lyncc.netty.heartbeat2; import io.netty.channel.Channel; import io.netty.channel.socket.SocketChannel; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class NettyChannelMap { private static Map map = new ConcurrentHashMap(); public static void add(String clientId,SocketChannel socketChannel){ map.put(clientId, socketChannel); } public static Channel get(String clientId){ return map.get(clientId); } public static void remove(SocketChannel socketChannel){ for(Map.Entry entry : map.entrySet()){ if(entry.getValue() == socketChannel){ map.remove(entry.getKey()); } } } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/NettyClientBootstrap.java ================================================ package com.lyncc.netty.heartbeat2; import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.concurrent.DefaultEventExecutorGroup; import io.netty.util.concurrent.EventExecutorGroup; import java.util.concurrent.TimeUnit; public class NettyClientBootstrap { private int port; private String host; private SocketChannel socketChannel; private static final EventExecutorGroup group = new DefaultEventExecutorGroup(20); public NettyClientBootstrap(int port, String host) throws InterruptedException { this.port = port; this.host = host; start(); } private void start() throws InterruptedException { EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.channel(NioSocketChannel.class); bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.group(eventLoopGroup); bootstrap.remoteAddress(host, port); bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new IdleStateHandler(20, 10, 0)); socketChannel.pipeline().addLast(new ObjectEncoder()); socketChannel.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null))); socketChannel.pipeline().addLast(new NettyClientHandler()); } }); ChannelFuture future = bootstrap.connect(host, port).sync(); if (future.isSuccess()) { socketChannel = (SocketChannel) future.channel(); System.out.println("connect server 成功---------"); } } public static void main(String[] args) throws InterruptedException { Constants.setClientId("001"); NettyClientBootstrap bootstrap = new NettyClientBootstrap(18080, "localhost"); LoginMsg loginMsg = new LoginMsg(); loginMsg.setPassword("yao"); loginMsg.setUserName("robin"); bootstrap.socketChannel.writeAndFlush(loginMsg); while (true) { TimeUnit.SECONDS.sleep(3); AskMsg askMsg = new AskMsg(); AskParams askParams = new AskParams(); askParams.setAuth("authToken"); askMsg.setParams(askParams); bootstrap.socketChannel.writeAndFlush(askMsg); } } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/NettyClientHandler.java ================================================ package com.lyncc.netty.heartbeat2; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.ReferenceCountUtil; public class NettyClientHandler extends SimpleChannelInboundHandler { //利用写空闲发送心跳检测消息 @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent e = (IdleStateEvent) evt; switch (e.state()) { case WRITER_IDLE: PingMsg pingMsg=new PingMsg(); ctx.writeAndFlush(pingMsg); System.out.println("send ping to server----------"); break; default: break; } } } @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, BaseMsg baseMsg) throws Exception { MsgType msgType=baseMsg.getType(); switch (msgType){ case LOGIN:{ //向服务器发起登录 LoginMsg loginMsg=new LoginMsg(); loginMsg.setPassword("yao"); loginMsg.setUserName("robin"); channelHandlerContext.writeAndFlush(loginMsg); }break; case PING:{ System.out.println("receive ping from server----------"); }break; case ASK:{ ReplyClientBody replyClientBody=new ReplyClientBody("client info **** !!!"); ReplyMsg replyMsg=new ReplyMsg(); replyMsg.setBody(replyClientBody); channelHandlerContext.writeAndFlush(replyMsg); }break; case REPLY:{ ReplyMsg replyMsg=(ReplyMsg)baseMsg; ReplyServerBody replyServerBody=(ReplyServerBody)replyMsg.getBody(); System.out.println("receive client msg: "+replyServerBody.getServerInfo()); } default:break; } ReferenceCountUtil.release(msgType); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { Channel incoming = ctx.channel(); System.out.println("SimpleChatClient:"+incoming.remoteAddress()+"异常"); cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/NettyServerBootstrap.java ================================================ package com.lyncc.netty.heartbeat2; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; 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.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.util.concurrent.TimeUnit; public class NettyServerBootstrap { private int port; private SocketChannel socketChannel; public NettyServerBootstrap(int port) throws InterruptedException { this.port = port; bind(); } private void bind() throws InterruptedException { EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); // 通过NoDelay禁用Nagle,使消息立即发出去,不用等待到一定的数据量才发出去 bootstrap.group(boss, worker).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128) .handler(new LoggingHandler(LogLevel.INFO)).option(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = socketChannel.pipeline(); p.addLast(new ObjectEncoder()); p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null))); p.addLast(new NettyServerHandler()); } }); ChannelFuture f = bootstrap.bind(port).sync(); if (f.isSuccess()) { System.out.println("server start---------------"); } } public static void main(String []args) throws InterruptedException { new NettyServerBootstrap(18080); while (true){ SocketChannel channel=(SocketChannel)NettyChannelMap.get("001"); if(channel!=null){ AskMsg askMsg=new AskMsg(); channel.writeAndFlush(askMsg); } TimeUnit.SECONDS.sleep(5); } } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/NettyServerHandler.java ================================================ package com.lyncc.netty.heartbeat2; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.SocketChannel; import io.netty.util.ReferenceCountUtil; public class NettyServerHandler extends SimpleChannelInboundHandler { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { NettyChannelMap.remove((SocketChannel) ctx.channel()); } @Override protected void channelRead0(ChannelHandlerContext ctx, BaseMsg msg) throws Exception { if (MsgType.LOGIN.equals(msg.getType())) { LoginMsg loginMsg = (LoginMsg) msg; if ("robin".equals(loginMsg.getUserName()) && "yao".equals(loginMsg.getPassword())) { NettyChannelMap.add(loginMsg.getClientId(), (SocketChannel) ctx.channel()); System.out.println("client" + loginMsg.getClientId() + " 登录成功"); } } else { if (NettyChannelMap.get(msg.getClientId()) == null) { // 说明未登录,或者连接断了,服务器向客户端发起登录请求,让客户端重新登录 LoginMsg loginMsg = new LoginMsg(); ctx.channel().writeAndFlush(loginMsg); } } switch (msg.getType()){ case PING:{ PingMsg pingMsg=(PingMsg)msg; PingMsg replyPing=new PingMsg(); NettyChannelMap.get(pingMsg.getClientId()).writeAndFlush(replyPing); }break; case ASK:{ //收到客户端的请求 AskMsg askMsg=(AskMsg)msg; if("authToken".equals(askMsg.getParams().getAuth())){ ReplyServerBody replyBody=new ReplyServerBody("server info"); ReplyMsg replyMsg=new ReplyMsg(); replyMsg.setBody(replyBody); NettyChannelMap.get(askMsg.getClientId()).writeAndFlush(replyMsg); } }break; case REPLY:{ //收到客户端回复 ReplyMsg replyMsg=(ReplyMsg)msg; ReplyClientBody clientBody=(ReplyClientBody)replyMsg.getBody(); System.out.println("receive client msg: "+clientBody.getClientInfo()); }break; default:break; } ReferenceCountUtil.release(msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { Channel incoming = ctx.channel(); System.out.println("server SimpleChatClient:"+incoming.remoteAddress()+"异常"); cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/PingMsg.java ================================================ package com.lyncc.netty.heartbeat2; public class PingMsg extends BaseMsg{ public PingMsg() { super(); setType(MsgType.PING); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/ReplyBody.java ================================================ package com.lyncc.netty.heartbeat2; import java.io.Serializable; public class ReplyBody implements Serializable{ /** * */ private static final long serialVersionUID = 1L; } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/ReplyClientBody.java ================================================ package com.lyncc.netty.heartbeat2; public class ReplyClientBody extends ReplyBody { private String clientInfo; public ReplyClientBody(String clientInfo) { this.clientInfo = clientInfo; } public String getClientInfo() { return clientInfo; } public void setClientInfo(String clientInfo) { this.clientInfo = clientInfo; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/ReplyMsg.java ================================================ package com.lyncc.netty.heartbeat2; public class ReplyMsg extends BaseMsg { public ReplyMsg() { super(); setType(MsgType.REPLY); } private ReplyBody body; public ReplyBody getBody() { return body; } public void setBody(ReplyBody body) { this.body = body; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeat2/ReplyServerBody.java ================================================ package com.lyncc.netty.heartbeat2; public class ReplyServerBody extends ReplyBody { private String serverInfo; public ReplyServerBody(String serverInfo) { this.serverInfo = serverInfo; } public String getServerInfo() { return serverInfo; } public void setServerInfo(String serverInfo) { this.serverInfo = serverInfo; } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeats/HeartBeatClientHandler.java ================================================ package com.lyncc.netty.heartbeats; import java.util.Date; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter { private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat", CharsetUtil.UTF_8)); private static final int TRY_TIMES = 3; private int currentTime = 0; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("激活时间是:"+new Date()); System.out.println("HeartBeatClientHandler channelActive"); ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("停止时间是:"+new Date()); System.out.println("HeartBeatClientHandler channelInactive"); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("循环触发时间:"+new Date()); if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.WRITER_IDLE) { if(currentTime <= TRY_TIMES){ System.out.println("currentTime:"+currentTime); currentTime++; ctx.channel().writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()); } } } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String message = (String) msg; System.out.println(message); if (message.equals("Heartbeat")) { ctx.write("has read message from server"); ctx.flush(); } ReferenceCountUtil.release(msg); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeats/HeartBeatServer.java ================================================ package com.lyncc.netty.heartbeats; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; public class HeartBeatServer { private int port; public HeartBeatServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS)); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HeartBeatServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new HeartBeatServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeats/HeartBeatServerHandler.java ================================================ package com.lyncc.netty.heartbeats; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; public class HeartBeatServerHandler extends ChannelInboundHandlerAdapter { private int loss_connect_time = 0; @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE) { loss_connect_time++; System.out.println("5 秒没有接收到客户端的信息了"); if (loss_connect_time > 2) { System.out.println("关闭这个不活跃的channel"); ctx.channel().close(); } } } else { super.userEventTriggered(ctx, evt); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress() + "->Server :" + msg.toString()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/heartbeats/HeartBeatsClient.java ================================================ package com.lyncc.netty.heartbeats; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; public class HeartBeatsClient { public void connect(int port, String host) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); ChannelFuture future = null; try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new LoggingHandler(LogLevel.INFO)) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("ping", new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS)); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast(new HeartBeatClientHandler()); } }); future = b.connect(host, port).sync(); future.channel().closeFuture().sync(); } finally { // group.shutdownGracefully(); if (null != future) { if (future.channel() != null && future.channel().isOpen()) { future.channel().close(); } } System.out.println("准备重连"); connect(port, host); System.out.println("重连成功"); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new HeartBeatsClient().connect(port, "127.0.0.1"); } } ================================================ FILE: src/main/java/com/lyncc/netty/hello/HelloWorldClient.java ================================================ package com.lyncc.netty.hello; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress; import java.net.SocketAddress; public class HelloWorldClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { initChannel(); } public static void initChannel() throws InterruptedException{ // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("decoder", new StringDecoder()); p.addLast("encoder", new StringEncoder()); p.addLast(new HelloWorldClientHandler()); } }); // SocketAddress socketAddress = InetSocketAddress.createUnresolved(address.getHost(), address.getPort()); SocketAddress socketAddress = new InetSocketAddress(HOST, PORT); ChannelFuture future = b.connect(socketAddress).sync(); future.channel().writeAndFlush("hello world"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/hello/HelloWorldClientHandler.java ================================================ package com.lyncc.netty.hello; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter{ @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("HelloWorldClientHandler Active"); ctx.fireChannelActive(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("HelloWorldClientHandler read Message:"+msg); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("HelloWorldClientHandler inActive==========="); super.channelInactive(ctx); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/hello/HelloWorldServer.java ================================================ package com.lyncc.netty.hello; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress; public class HelloWorldServer { private int port; public HelloWorldServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap(); sbs.group(bossGroup,workerGroup); sbs.channel(NioServerSocketChannel.class); sbs.childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HelloWorldServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new HelloWorldServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/hello/HelloWorldServerHandler.java ================================================ package com.lyncc.netty.hello; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class HelloWorldServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("123123"); super.channelActive(ctx); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString()); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/AcceptorIdleStateTrigger.java ================================================ package com.lyncc.netty.idle; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; @ChannelHandler.Sharable public class AcceptorIdleStateTrigger extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState state = ((IdleStateEvent) evt).state(); if (state == IdleState.READER_IDLE) { throw new Exception("idle exception"); } } else { super.userEventTriggered(ctx, evt); } } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/ChannelHandlerHolder.java ================================================ package com.lyncc.netty.idle; import io.netty.channel.ChannelHandler; /** * * 客户端的ChannelHandler集合,由子类实现,这样做的好处: * 继承这个接口的所有子类可以很方便地获取ChannelPipeline中的Handlers * 获取到handlers之后方便ChannelPipeline中的handler的初始化和在重连的时候也能很方便 * 地获取所有的handlers */ public interface ChannelHandlerHolder { ChannelHandler[] handlers(); } ================================================ FILE: src/main/java/com/lyncc/netty/idle/ConnectionWatchdog.java ================================================ package com.lyncc.netty.idle; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; import java.util.concurrent.TimeUnit; /** * * 重连检测狗,当发现当前的链路不稳定关闭之后,进行12次重连 */ @Sharable public abstract class ConnectionWatchdog extends ChannelInboundHandlerAdapter implements TimerTask ,ChannelHandlerHolder{ private final Bootstrap bootstrap; private final Timer timer; private final int port; private final String host; private volatile boolean reconnect = true; private int attempts; public ConnectionWatchdog(Bootstrap bootstrap, Timer timer, int port,String host, boolean reconnect) { this.bootstrap = bootstrap; this.timer = timer; this.port = port; this.host = host; this.reconnect = reconnect; } /** * channel链路每次active的时候,将其连接的次数重新☞ 0 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("当前链路已经激活了,重连尝试次数重新置为0"); attempts = 0; ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("链接关闭"); if(reconnect){ System.out.println("链接关闭,将进行重连"); if (attempts < 12) { attempts++; //重连的间隔时间会越来越长 int timeout = 2 << attempts; timer.newTimeout(this, timeout, TimeUnit.MILLISECONDS); } } ctx.fireChannelInactive(); } public void run(Timeout timeout) throws Exception { ChannelFuture future; //bootstrap已经初始化好了,只需要将handler填入就可以了 synchronized (bootstrap) { bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(handlers()); } }); future = bootstrap.connect(host,port); } //future对象 future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { boolean succeed = f.isSuccess(); //如果重连失败,则调用ChannelInactive方法,再次出发重连事件,一直尝试12次,如果失败则不再重连 if (!succeed) { System.out.println("重连失败"); f.channel().pipeline().fireChannelInactive(); }else{ System.out.println("重连成功"); } } }); } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/ConnectorIdleStateTrigger.java ================================================ package com.lyncc.netty.idle; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.CharsetUtil; @Sharable public class ConnectorIdleStateTrigger extends ChannelInboundHandlerAdapter { private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat", CharsetUtil.UTF_8)); @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState state = ((IdleStateEvent) evt).state(); if (state == IdleState.WRITER_IDLE) { // write heartbeat to server ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()); } } else { super.userEventTriggered(ctx, evt); } } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/HeartBeatClientHandler.java ================================================ package com.lyncc.netty.idle; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; import java.util.Date; @Sharable public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("激活时间是:"+new Date()); System.out.println("HeartBeatClientHandler channelActive"); ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("停止时间是:"+new Date()); System.out.println("HeartBeatClientHandler channelInactive"); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String message = (String) msg; System.out.println(message); if (message.equals("Heartbeat")) { ctx.write("has read message from server"); ctx.flush(); } ReferenceCountUtil.release(msg); } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/HeartBeatServer.java ================================================ package com.lyncc.netty.idle; 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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; public class HeartBeatServer { private final AcceptorIdleStateTrigger idleStateTrigger = new AcceptorIdleStateTrigger(); private int port; public HeartBeatServer(int port) { this.port = port; } public void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)) .localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS)); ch.pipeline().addLast(idleStateTrigger); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HeartBeatServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new HeartBeatServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/HeartBeatServerHandler.java ================================================ package com.lyncc.netty.idle; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class HeartBeatServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server channelRead.."); System.out.println(ctx.channel().remoteAddress() + "->Server :" + msg.toString()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/idle/HeartBeatsClient.java ================================================ package com.lyncc.netty.idle; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.HashedWheelTimer; import java.util.concurrent.TimeUnit; public class HeartBeatsClient { protected final HashedWheelTimer timer = new HashedWheelTimer(); private Bootstrap boot; private final ConnectorIdleStateTrigger idleStateTrigger = new ConnectorIdleStateTrigger(); public void connect(int port, String host) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); boot = new Bootstrap(); boot.group(group).channel(NioSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)); final ConnectionWatchdog watchdog = new ConnectionWatchdog(boot, timer, port,host, true) { public ChannelHandler[] handlers() { return new ChannelHandler[] { this, new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS), idleStateTrigger, new StringDecoder(), new StringEncoder(), new HeartBeatClientHandler() }; } }; ChannelFuture future; //进行连接 try { synchronized (boot) { boot.handler(new ChannelInitializer() { //初始化channel @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(watchdog.handlers()); } }); future = boot.connect(host,port); } // 以下代码在synchronized同步块外面是安全的 future.sync(); } catch (Throwable t) { throw new Exception("connects to fails", t); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { int port = 8080; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { // 采用默认值 } } new HeartBeatsClient().connect(port, "127.0.0.1"); } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/Constants.java ================================================ package com.lyncc.netty.keepalive; public class Constants { public static final int REQ_CODE = 1 ; public static final int RET_CODE = 2 ; } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/Heartbeat.java ================================================ package com.lyncc.netty.keepalive; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; public class Heartbeat extends SimpleChannelInboundHandler{ //失败计数器:未收到client端发送的ping请求 private int unRecPingTimes = 0 ; //每个chanel对应一个线程,此处用来存储对应于每个线程的一些基础数据,此处不一定要为KeepAliveMessage对象 ThreadLocal localMsgInfo = new ThreadLocal(); // 定义客户端没有收到服务端的pong消息的最大次数 private static final int MAX_UN_REC_PING_TIMES = 3; @Override protected void channelRead0(ChannelHandlerContext ctx, KeepAliveMessage msg) throws Exception { System.out.println(ctx.channel().remoteAddress() + " Say : sn=" + msg.getSn()+",reqcode="+msg.getReqCode()); if(Utils.notEmpty(msg.getSn())&&msg.getReqCode()==1){ msg.setReqCode(Constants.RET_CODE); ctx.channel().writeAndFlush(msg); // 失败计数器清零 unRecPingTimes = 0; if(localMsgInfo.get()==null){ KeepAliveMessage localMsg = new KeepAliveMessage(); localMsg.setSn(msg.getSn()); localMsgInfo.set(localMsg); } }else{ ctx.channel().close(); } } public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE) { /*读超时*/ System.out.println("===服务端===(READER_IDLE 读超时)"); // 失败计数器次数大于等于3次的时候,关闭链接,等待client重连 if(unRecPingTimes >= MAX_UN_REC_PING_TIMES){ System.out.println("===服务端===(读超时,关闭chanel)"); // 连续超过N次未收到client的ping消息,那么关闭该通道,等待client重连 ctx.channel().close(); }else{ // 失败计数器加1 unRecPingTimes++; } } else if (event.state() == IdleState.WRITER_IDLE) { /*写超时*/ System.out.println("===服务端===(WRITER_IDLE 写超时)"); } else if (event.state() == IdleState.ALL_IDLE) { /*总超时*/ System.out.println("===服务端===(ALL_IDLE 总超时)"); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("错误原因:"+cause.getMessage()); if(localMsgInfo.get()!=null){ /* * 从管理集合中移除设备号等唯一标示,标示设备离线 */ // TODO } ctx.channel().close(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active "); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // 关闭,等待重连 ctx.close(); if(localMsgInfo.get()!=null){ /* * 从管理集合中移除设备号等唯一标示,标示设备离线 */ // TODO } System.out.println("===服务端===(客户端失效)"); } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/KeepAliveClient.java ================================================ package com.lyncc.netty.keepalive; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class KeepAliveClient { private String host ; private int port ; private EventLoopGroup group ; private Bootstrap b ; private Channel ch ; // 定义客户端没有收到服务端的pong消息的最大次数 private static final int MAX_UN_REC_PONG_TIMES = 3; // 多长时间未请求后,发送心跳 private static final int WRITE_WAIT_SECONDS = 5; // 隔N秒后重连 private static final int RE_CONN_WAIT_SECONDS = 5; // 客户端连续N次没有收到服务端的pong消息 计数器 private int unRecPongTimes = 0 ; private ScheduledExecutorService executorService ; // 是否停止 private boolean isStop = false ; public KeepAliveClient(String host, int port) { this.host = host ; this.port = port ; group = new NioEventLoopGroup(); b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).handler(new HeartbeatInitializer()); } public void start() { connServer(); } private void connServer(){ isStop = false; if(executorService!=null){ executorService.shutdown(); } executorService = Executors.newScheduledThreadPool(1); executorService.scheduleWithFixedDelay(new Runnable() { boolean isConnSucc = true; public void run() { try { // 重置计数器 unRecPongTimes = 0; // 连接服务端 if(ch!=null&&ch.isOpen()){ ch.close(); } ch = b.connect(host, port).sync().channel(); // 此方法会阻塞 // ch.closeFuture().sync(); System.out.println("connect server finish"); } catch (Exception e) { e.printStackTrace(); isConnSucc = false ; } finally{ if(isConnSucc){ if(executorService!=null){ executorService.shutdown(); } } } } }, RE_CONN_WAIT_SECONDS, RE_CONN_WAIT_SECONDS, TimeUnit.SECONDS); } public class HeartbeatInitializer extends ChannelInitializer { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader()))); pipeline.addLast("encoder", new ObjectEncoder()); pipeline.addLast("ping", new IdleStateHandler(0, WRITE_WAIT_SECONDS, 0,TimeUnit.SECONDS)); // 客户端的逻辑 pipeline.addLast("handler", new ClientHandler()); } } public class ClientHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, KeepAliveMessage msg) throws Exception { System.out.println("Server say : sn=" + msg.getSn()+",reqcode="+msg.getReqCode()); if (Constants.RET_CODE == msg.getReqCode()) { // 计数器清零 unRecPongTimes = 0; } } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active "); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); /* * 重连 */ if(!isStop){ connServer(); } } public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.READER_IDLE) { /*读超时*/ System.out.println("===服务端===(READER_IDLE 读超时)"); } else if (event.state() == IdleState.WRITER_IDLE) { /*写超时*/ System.out.println("===服务端===(WRITER_IDLE 写超时)"); if(unRecPongTimes < MAX_UN_REC_PONG_TIMES){ ctx.channel().writeAndFlush(getSrcMsg()) ; unRecPongTimes++; }else{ ctx.channel().close(); } } else if (event.state() == IdleState.ALL_IDLE) { /*总超时*/ System.out.println("===服务端===(ALL_IDLE 总超时)"); } } } } private KeepAliveMessage getSrcMsg(){ KeepAliveMessage keepAliveMessage = new KeepAliveMessage(); // 设备码 keepAliveMessage.setSn("sn_123456abcdfef"); keepAliveMessage.setReqCode(Constants.REQ_CODE); return keepAliveMessage ; } public void stop(){ isStop = true; if(ch!=null&&ch.isOpen()){ ch.close(); } if(executorService!=null){ executorService.shutdown(); } } /** * @param args */ public static void main(String[] args) { KeepAliveClient keepAliveServer = new KeepAliveClient("127.0.0.1",1666); keepAliveServer.start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/KeepAliveMessage.java ================================================ package com.lyncc.netty.keepalive; public class KeepAliveMessage implements java.io.Serializable{ private static final long serialVersionUID = 479148324800517968L; private String sn ; private int reqCode ; // 1:心跳请求 2:心跳反馈 public String getSn() { return sn; } public void setSn(String sn) { this.sn = sn; } public int getReqCode() { return reqCode; } public void setReqCode(int reqCode) { this.reqCode = reqCode; } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/KeepAliveServer.java ================================================ package com.lyncc.netty.keepalive; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class KeepAliveServer { private int port ; public KeepAliveServer(int port) { this.port = port; } ChannelFuture f ; ServerBootstrap b ; public void startServer() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { b = new ServerBootstrap(); b.group(bossGroup, workerGroup); b.channel(NioServerSocketChannel.class); b.childHandler(new KeepAliveServerInitializer()); // 服务器绑定端口监听 f = b.bind(port).sync(); // 监听服务器关闭监听,此方法会阻塞 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/KeepAliveServerInitializer.java ================================================ package com.lyncc.netty.keepalive; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; public class KeepAliveServerInitializer extends ChannelInitializer{ // 设置6秒检测chanel是否接受过心跳数据 private static final int READ_WAIT_SECONDS = 6; // 定义客户端没有收到服务端的pong消息的最大次数 private static final int MAX_UN_REC_PING_TIMES = 3; @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader()))); pipeline.addLast("encoder", new ObjectEncoder()); pipeline.addLast("pong", new IdleStateHandler(READ_WAIT_SECONDS, 0, 0,TimeUnit.SECONDS)); pipeline.addLast("handler", new Heartbeat()); } } ================================================ FILE: src/main/java/com/lyncc/netty/keepalive/Utils.java ================================================ package com.lyncc.netty.keepalive; import java.util.Collection; public class Utils { /** * 判断对象是否为空
* 不为空返回true,为空返回false * * @param o * @return */ public static boolean notEmpty(Object o) { boolean notEmpty = false; if (o instanceof String) { String s = (String) o; if (s != null && !"".equals(s) && !"undefined".equals(s) && !"null".equals(s)) { notEmpty = true; } } else if (o instanceof Collection) { Collection c = (Collection) o; if (c != null && c.size() > 0) { notEmpty = true; } } else if (o instanceof Object[]) { Object[] arr = (Object[]) o; if (arr != null && arr.length > 0) { notEmpty = true; } } else if (o != null) { return true; } return notEmpty; } } ================================================ FILE: src/main/java/com/lyncc/netty/nio/EchoClient.java ================================================ package com.lyncc.netty.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Set; public class EchoClient { public static void main(String[] args) throws IOException { SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); InetSocketAddress s = new InetSocketAddress("localhost", 2000); channel.connect(s); Selector selector = Selector.open(); channel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ); Charset charset = Charset.forName("GBK"); boolean isFinished = false; while (!isFinished) { int num = selector.select(); if (num > 0) { Set keys = selector.selectedKeys(); for (SelectionKey k : keys) { if (k.isConnectable()) { SocketChannel sc = (SocketChannel) k.channel(); sc.configureBlocking(false); sc.finishConnect(); sc.register(selector, SelectionKey.OP_READ); ByteBuffer echoBuffer = ByteBuffer.allocate(1024); ByteBuffer info = charset.encode("好了克隆技术杜洛克防水堵漏开发!"); echoBuffer.put(info); echoBuffer.flip(); sc.write(echoBuffer); echoBuffer.clear(); } else if (k.isValid() && k.isReadable()) { ByteBuffer echoBuffer = ByteBuffer.allocate(1024); SocketChannel sc = (SocketChannel) k.channel(); sc.read(echoBuffer); echoBuffer.flip(); System.out.println("echo server return:" + charset.decode(echoBuffer).toString()); echoBuffer.clear(); isFinished = true; k.cancel(); sc.close(); selector.close(); } } } } } } ================================================ FILE: src/main/java/com/lyncc/netty/nio/MultiPortEchoServer.java ================================================ package com.lyncc.netty.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; public class MultiPortEchoServer { private Charset charset=Charset.forName("GBK"); private int[] ports; /** * @param args */ public static void main(String[] args) { int[] ps = {2000,2001}; //默认监听2000,2001端口 new MultiPortEchoServer(ps); } public MultiPortEchoServer(int[] ports){ this.ports = ports; try { go(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void go() throws IOException{ Selector selector = Selector.open(); for(int i=0;i keys = selector.selectedKeys(); Iterator iter = keys.iterator(); while(iter.hasNext()){ SelectionKey key = iter.next(); if((key.readyOps()&SelectionKey.OP_ACCEPT)==SelectionKey.OP_ACCEPT){ ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); iter.remove(); }else if((key.readyOps()&SelectionKey.OP_READ)==SelectionKey.OP_READ){ SocketChannel sc = (SocketChannel) key.channel(); if(!sc.isOpen()){ selector = Selector.open(); }else{ ByteBuffer echoBuffer = ByteBuffer.allocate(1024); //int x = sc.read(echoBuffer); while(sc.read(echoBuffer)>0){ System.out.println( "Echoed "+charset.decode(echoBuffer).toString()+" from "+sc.socket().getInetAddress().getHostAddress() ); echoBuffer.flip(); sc.write(echoBuffer); echoBuffer.clear(); } iter.remove(); /*返回信息后关闭连接*/ key.cancel(); sc.close(); } } } keys.clear(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/nio/package-info.java ================================================ /** * */ /** * @author BazingaLyn * @description * @time * @modifytime */ package com.lyncc.netty.nio; ================================================ FILE: src/main/java/com/lyncc/netty/production/ChannelHandlerHolder.java ================================================ /* * Copyright (c) 2015 The Jupiter Project * * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production; import io.netty.channel.ChannelHandler; /** * jupiter * org.jupiter.transport.netty.handler * * @author jiachun.fjc */ public interface ChannelHandlerHolder { ChannelHandler[] handlers(); } ================================================ FILE: src/main/java/com/lyncc/netty/production/ConnectionWatchdog.java ================================================ package com.lyncc.netty.production; import static java.util.concurrent.TimeUnit.MILLISECONDS; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ChannelHandler.Sharable public abstract class ConnectionWatchdog extends ChannelInboundHandlerAdapter implements TimerTask, ChannelHandlerHolder { private static final Logger logger = LoggerFactory.getLogger(ConnectionWatchdog.class); private final Bootstrap bootstrap; private final Timer timer; private final int port; private final String host; private volatile boolean reconnect = true; private int attempts; public ConnectionWatchdog(Bootstrap bootstrap, Timer timer, int port,String host) { this.bootstrap = bootstrap; this.timer = timer; this.port = port; this.host = host; } public boolean isReconnect() { return reconnect; } public void setReconnect(boolean reconnect) { this.reconnect = reconnect; } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); attempts = 0; logger.info("Connects with {}.", channel); ctx.fireChannelActive(); } /** * 因为链路断掉之后,会触发channelInActive方法,进行重连 */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { boolean doReconnect = reconnect; if (doReconnect) { if (attempts < 12) { attempts++; } long timeout = 2 << attempts; timer.newTimeout(this, timeout, MILLISECONDS); } logger.warn("Disconnects with {}, port: {},host {}, reconnect: {}.", ctx.channel(), port,host, doReconnect); ctx.fireChannelInactive(); } public void run(Timeout timeout) throws Exception { ChannelFuture future; synchronized (bootstrap) { bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(handlers()); } }); future = bootstrap.connect(host,port); } future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { boolean succeed = f.isSuccess(); logger.warn("Reconnects with {}, {}.", host+":"+port, succeed ? "succeed" : "failed"); if (!succeed) { f.channel().pipeline().fireChannelInactive(); } } }); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/client/connector/ClientConnector.java ================================================ package com.lyncc.netty.production.client.connector; import io.netty.channel.Channel; /** * * @author BazingaLyn * @description * @time 2016年7月21日10:47:12 * @modifytime */ public interface ClientConnector { Channel connect(int port,String host); void shutdownGracefully(); } ================================================ FILE: src/main/java/com/lyncc/netty/production/client/connector/ConnectorIdleStateTrigger.java ================================================ package com.lyncc.netty.production.client.connector; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lyncc.netty.production.common.Heartbeats; /** * 心跳trigger * @author BazingaLyn * @copyright fjc * @time */ @ChannelHandler.Sharable public class ConnectorIdleStateTrigger extends ChannelInboundHandlerAdapter { private static final Logger logger = LoggerFactory.getLogger(ConnectorIdleStateTrigger.class); @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState state = ((IdleStateEvent) evt).state(); if (state == IdleState.WRITER_IDLE) { logger.info("need send heartbeats"); ctx.writeAndFlush(Heartbeats.heartbeatContent()); } } else { super.userEventTriggered(ctx, evt); } } } ================================================ FILE: src/main/java/com/lyncc/netty/production/client/connector/DefaultCommonClientConnector.java ================================================ package com.lyncc.netty.production.client.connector; import static com.lyncc.netty.production.common.NettyCommonProtocol.ACK; import static com.lyncc.netty.production.common.NettyCommonProtocol.MAGIC; import static com.lyncc.netty.production.common.NettyCommonProtocol.RESPONSE; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_1; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_2; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_3; import static com.lyncc.netty.production.serializer.SerializerHolder.serializerImpl; import static java.util.concurrent.TimeUnit.SECONDS; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.DefaultMessageSizeEstimator; import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.HashedWheelTimer; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lyncc.netty.production.ConnectionWatchdog; import com.lyncc.netty.production.common.Acknowledge; import com.lyncc.netty.production.common.Message; import com.lyncc.netty.production.common.NativeSupport; import com.lyncc.netty.production.common.NettyCommonProtocol; import com.lyncc.netty.production.common.exception.ConnectFailedException; import com.lyncc.netty.production.srv.acceptor.AcknowledgeEncoder; /** * * @author BazingaLyn * @description 默认的一些比较常用的client的配置 * @time 2016年7月22日14:54:37 * @modifytime */ public class DefaultCommonClientConnector extends NettyClientConnector { private static final Logger logger = LoggerFactory.getLogger(DefaultCommonClientConnector.class); //每个连接维护一个channel private volatile Channel channel; //信息处理的handler private final MessageHandler handler = new MessageHandler(); //编码 private final MessageEncoder encoder = new MessageEncoder(); //ack private final AcknowledgeEncoder ackEncoder = new AcknowledgeEncoder(); private final ConcurrentMap messagesNonAcks = new ConcurrentHashMap(); protected final HashedWheelTimer timer = new HashedWheelTimer(new ThreadFactory() { private AtomicInteger threadIndex = new AtomicInteger(0); public Thread newThread(Runnable r) { return new Thread(r, "NettyClientConnectorExecutor_" + this.threadIndex.incrementAndGet()); } }); //心跳trigger private final ConnectorIdleStateTrigger idleStateTrigger = new ConnectorIdleStateTrigger(); public DefaultCommonClientConnector() { init(); } @Override protected void init() { super.init(); bootstrap().option(ChannelOption.ALLOCATOR, allocator) .option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT) .option(ChannelOption.SO_REUSEADDR, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) SECONDS.toMillis(3)) .channel(NioSocketChannel.class); bootstrap().option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.ALLOW_HALF_CLOSURE, false); } public Channel connect(int port, String host) { final Bootstrap boot = bootstrap(); // 重连watchdog final ConnectionWatchdog watchdog = new ConnectionWatchdog(boot, timer, port,host) { public ChannelHandler[] handlers() { return new ChannelHandler[] { //将自己[ConnectionWatchdog]装载到handler链中,当链路断掉之后,会触发ConnectionWatchdog #channelInActive方法 this, //每隔30s的时间触发一次userEventTriggered的方法,并且指定IdleState的状态位是WRITER_IDLE new IdleStateHandler(0, 30, 0, TimeUnit.SECONDS), //实现userEventTriggered方法,并在state是WRITER_IDLE的时候发送一个心跳包到sever端,告诉server端我还活着 idleStateTrigger, new MessageDecoder(), encoder, ackEncoder, handler }; }}; watchdog.setReconnect(true); try { ChannelFuture future; synchronized (bootstrapLock()) { boot.handler(new ChannelInitializer() { @Override protected void initChannel(NioSocketChannel ch) throws Exception { ch.pipeline().addLast(watchdog.handlers()); } }); future = boot.connect("127.0.0.1", 20011); } future.sync(); channel = future.channel(); } catch (Throwable t) { throw new ConnectFailedException("connects to [" + host + ":"+port+"] fails", t); } return channel; } @ChannelHandler.Sharable class MessageHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if(msg instanceof Acknowledge){ logger.info("收到server端的Ack信息,无需再次发送信息"); messagesNonAcks.remove(((Acknowledge)msg).sequence()); } } } /** * ************************************************************************************************** * Protocol * ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ * 2 │ 1 │ 1 │ 8 │ 4 │ * ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ * │ │ │ │ │ * │ MAGIC Sign Status Invoke Id Body Length Body Content │ * │ │ │ │ │ * └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ * * 消息头16个字节定长 * = 2 // MAGIC = (short) 0xbabe * + 1 // 消息标志位, 用来表示消息类型 * + 1 // 空 * + 8 // 消息 id long 类型 * + 4 // 消息体body长度, int类型 */ @ChannelHandler.Sharable static class MessageEncoder extends MessageToByteEncoder { @Override protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception { byte[] bytes = serializerImpl().writeObject(msg); out.writeShort(MAGIC) .writeByte(msg.sign()) .writeByte(0) .writeLong(0) .writeInt(bytes.length) .writeBytes(bytes); } } static class MessageDecoder extends ReplayingDecoder { public MessageDecoder() { super(State.HEADER_MAGIC); } // 协议头 private final NettyCommonProtocol header = new NettyCommonProtocol(); @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { switch (state()) { case HEADER_MAGIC: checkMagic(in.readShort()); // MAGIC checkpoint(State.HEADER_SIGN); case HEADER_SIGN: header.sign(in.readByte()); // 消息标志位 checkpoint(State.HEADER_STATUS); case HEADER_STATUS: in.readByte(); // no-op checkpoint(State.HEADER_ID); case HEADER_ID: header.id(in.readLong()); // 消息id checkpoint(State.HEADER_BODY_LENGTH); case HEADER_BODY_LENGTH: header.bodyLength(in.readInt()); // 消息体长度 checkpoint(State.BODY); case BODY: switch (header.sign()) { case RESPONSE: case SERVICE_1: case SERVICE_2: case SERVICE_3: { byte[] bytes = new byte[header.bodyLength()]; in.readBytes(bytes); Message msg = serializerImpl().readObject(bytes, Message.class); msg.sign(header.sign()); out.add(msg); break; } case ACK: { byte[] bytes = new byte[header.bodyLength()]; in.readBytes(bytes); Acknowledge ack = serializerImpl().readObject(bytes, Acknowledge.class); out.add(ack); break; } default: throw new IllegalArgumentException(); } checkpoint(State.HEADER_MAGIC); } } private static void checkMagic(short magic) throws Exception { if (MAGIC != magic) { throw new IllegalArgumentException(); } } enum State { HEADER_MAGIC, HEADER_SIGN, HEADER_STATUS, HEADER_ID, HEADER_BODY_LENGTH, BODY } } @Override protected EventLoopGroup initEventLoopGroup(int nWorkers, ThreadFactory workerFactory) { return NativeSupport.isSupportNativeET() ? new EpollEventLoopGroup(nWorkers, workerFactory) : new NioEventLoopGroup(nWorkers, workerFactory); } public static class MessageNonAck { private final long id; private final Message msg; private final Channel channel; private final long timestamp = System.currentTimeMillis(); public MessageNonAck(Message msg, Channel channel) { this.msg = msg; this.channel = channel; id = msg.sequence(); } } private class AckTimeoutScanner implements Runnable { public void run() { for (;;) { try { for (MessageNonAck m : messagesNonAcks.values()) { if (System.currentTimeMillis() - m.timestamp > SECONDS.toMillis(10)) { // 移除 if (messagesNonAcks.remove(m.id) == null) { continue; } if (m.channel.isActive()) { logger.warn("准备重新发送信息"); MessageNonAck msgNonAck = new MessageNonAck(m.msg, m.channel); messagesNonAcks.put(msgNonAck.id, msgNonAck); m.channel.writeAndFlush(m.msg) .addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); } } } Thread.sleep(300); } catch (Throwable t) { logger.error("An exception has been caught while scanning the timeout acknowledges {}.", t); } } } } { Thread t = new Thread(new AckTimeoutScanner(), "ack.timeout.scanner"); t.setDaemon(true); t.start(); } public void addNeedAckMessageInfo(MessageNonAck msgNonAck) { messagesNonAcks.put(msgNonAck.id, msgNonAck); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/client/connector/NettyClientConnector.java ================================================ package com.lyncc.netty.production.client.connector; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBufAllocator; import io.netty.channel.EventLoopGroup; import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.ThreadFactory; public abstract class NettyClientConnector implements ClientConnector { public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors(); private Bootstrap bootstrap; private EventLoopGroup worker; private int nWorkers; protected volatile ByteBufAllocator allocator; public NettyClientConnector() { this(AVAILABLE_PROCESSORS << 1); } public NettyClientConnector(int nWorkers) { this.nWorkers = nWorkers; } protected void init() { ThreadFactory workerFactory = new DefaultThreadFactory("client.connector"); worker = initEventLoopGroup(nWorkers, workerFactory); bootstrap = new Bootstrap().group(worker); } protected Bootstrap bootstrap() { return bootstrap; } protected Object bootstrapLock() { return bootstrap; } public void shutdownGracefully() { worker.shutdownGracefully(); } protected abstract EventLoopGroup initEventLoopGroup(int nWorkers, ThreadFactory workerFactory); } ================================================ FILE: src/main/java/com/lyncc/netty/production/client/connector/package-info.java ================================================ /** * */ /** * @author BazingaLyn * @description * @time * @modifytime */ package com.lyncc.netty.production.client.connector; ================================================ FILE: src/main/java/com/lyncc/netty/production/common/Acknowledge.java ================================================ /* * Copyright (c) 2015 The Jupiter Project * * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production.common; /** * ACK确认 * * jupiter * org.jupiter.transport * * @author jiachun.fjc */ public class Acknowledge { public Acknowledge() {} public Acknowledge(long sequence) { this.sequence = sequence; } private long sequence; // ACK序号 public long sequence() { return sequence; } public void sequence(long sequence) { this.sequence = sequence; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/Heartbeats.java ================================================ package com.lyncc.netty.production.common; import static com.lyncc.netty.production.common.NettyCommonProtocol.HEAD_LENGTH; import static com.lyncc.netty.production.common.NettyCommonProtocol.HEARTBEAT; import static com.lyncc.netty.production.common.NettyCommonProtocol.MAGIC; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; /** * * @author BazingaLyn * @description 心跳包 * @time * @modifytime */ public class Heartbeats { private static final ByteBuf HEARTBEAT_BUF; static { ByteBuf buf = Unpooled.buffer(HEAD_LENGTH); buf.writeShort(MAGIC); buf.writeByte(HEARTBEAT); buf.writeByte(0); buf.writeLong(0); buf.writeInt(0); HEARTBEAT_BUF = Unpooled.unmodifiableBuffer(Unpooled.unreleasableBuffer(buf)); } public static ByteBuf heartbeatContent() { return HEARTBEAT_BUF.duplicate(); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/Message.java ================================================ /* * Copyright (c) 2015 The Jupiter Project * * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production.common; import java.util.concurrent.atomic.AtomicLong; /** * 发布订阅信息的包装类. * * jupiter * org.jupiter.registry * * @author jiachun.fjc */ public class Message { private static final AtomicLong sequenceGenerator = new AtomicLong(0); private final long sequence; private short sign; private long version; // 版本号 private Object data; public Message() { this(sequenceGenerator.getAndIncrement()); } public Message(long sequence) { this.sequence = sequence; } public long sequence() { return sequence; } public short sign() { return sign; } public void sign(short sign) { this.sign = sign; } public long getVersion() { return version; } public void setVersion(long version) { this.version = version; } public Object data() { return data; } public void data(Object data) { this.data = data; } @Override public String toString() { return "Message{" + "sequence=" + sequence + ", sign=" + sign + ", version=" + version + ", data=" + data + '}'; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/NativeSupport.java ================================================ package com.lyncc.netty.production.common; /** * * @author BazingaLyn * @description * @copyright fjc * @time 2016年7月20日20:48:08 * @modifytime */ public final class NativeSupport { private static final boolean SUPPORT_NATIVE_ET; static { boolean epoll; try { Class.forName("io.netty.channel.epoll.Native"); epoll = true; } catch (Throwable e) { epoll = false; } SUPPORT_NATIVE_ET = epoll; } /** * The native socket transport for Linux using JNI. */ public static boolean isSupportNativeET() { return SUPPORT_NATIVE_ET; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/NettyCommonProtocol.java ================================================ package com.lyncc.netty.production.common; /** * * @author BazingaLyn * @description Netty的C/S端的之间约定的协议 * @time 2016年7月27日09:20:55 * @modifytime */ public class NettyCommonProtocol { /** 协议头长度 */ public static final int HEAD_LENGTH = 16; /** Magic */ public static final short MAGIC = (short) 0xbabe; /** Request */ public static final byte REQUEST = 1; /** Response */ public static final byte RESPONSE = 2; public static final byte SERVICE_1 = 3; public static final byte SERVICE_2 = 4; public static final byte SERVICE_3 = 5; public static final byte SERVICE_4 = 6; /** Acknowledge */ public static final byte ACK = 126; /** Heartbeat */ public static final byte HEARTBEAT = 127; private byte sign; private byte status; private long id; private int bodyLength; public byte sign() { return sign; } public void sign(byte sign) { this.sign = sign; } public byte status() { return status; } public void status(byte status) { this.status = status; } public long id() { return id; } public void id(long id) { this.id = id; } public int bodyLength() { return bodyLength; } public void bodyLength(int bodyLength) { this.bodyLength = bodyLength; } @Override public String toString() { return "NettyCommonProtocol [sign=" + sign + ", status=" + status + ", id=" + id + ", bodyLength=" + bodyLength + "]"; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/NettyEvent.java ================================================ /** * Copyright (C) 2010-2013 Alibaba Group Holding Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production.common; import io.netty.channel.Channel; /** * Netty产生的各种事件 * * @author shijia.wxr * @since 2013-7-13 */ public class NettyEvent { private final NettyEventType type; private final String remoteAddr; private final Channel channel; public NettyEvent(NettyEventType type, String remoteAddr, Channel channel) { this.type = type; this.remoteAddr = remoteAddr; this.channel = channel; } public NettyEventType getType() { return type; } public String getRemoteAddr() { return remoteAddr; } public Channel getChannel() { return channel; } @Override public String toString() { return "NettyEvent [type=" + type + ", remoteAddr=" + remoteAddr + ", channel=" + channel + "]"; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/NettyEventType.java ================================================ /** * Copyright (C) 2010-2013 Alibaba Group Holding Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production.common; /** * Netty产生的事件类型 * * @author shijia.wxr * @since 2013-7-13 */ public enum NettyEventType { CONNECT, CLOSE, IDLE, EXCEPTION } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/ServiceThread.java ================================================ package com.lyncc.netty.production.common; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class ServiceThread implements Runnable { private static final Logger stlog = LoggerFactory.getLogger(ServiceThread.class); protected final Thread thread; private static final long JoinTime = 90 * 1000; protected volatile boolean hasNotified = false; protected volatile boolean stoped = false; public ServiceThread() { this.thread = new Thread(this, this.getServiceName()); } public abstract String getServiceName(); public void start() { this.thread.start(); } public void shutdown() { this.shutdown(false); } public void stop() { this.stop(false); } public void makeStop() { this.stoped = true; stlog.info("makestop thread " + this.getServiceName()); } public void stop(final boolean interrupt) { this.stoped = true; stlog.info("stop thread " + this.getServiceName() + " interrupt " + interrupt); synchronized (this) { if (!this.hasNotified) { this.hasNotified = true; this.notify(); } } if (interrupt) { this.thread.interrupt(); } } public void shutdown(final boolean interrupt) { this.stoped = true; stlog.info("shutdown thread " + this.getServiceName() + " interrupt " + interrupt); synchronized (this) { if (!this.hasNotified) { this.hasNotified = true; this.notify(); } } try { if (interrupt) { this.thread.interrupt(); } long beginTime = System.currentTimeMillis(); this.thread.join(this.getJointime()); long eclipseTime = System.currentTimeMillis() - beginTime; stlog.info("join thread " + this.getServiceName() + " eclipse time(ms) " + eclipseTime + " " + this.getJointime()); } catch (InterruptedException e) { e.printStackTrace(); } } public void wakeup() { synchronized (this) { if (!this.hasNotified) { this.hasNotified = true; this.notify(); } } } protected void waitForRunning(long interval) { synchronized (this) { if (this.hasNotified) { this.hasNotified = false; this.onWaitEnd(); return; } try { this.wait(interval); } catch (InterruptedException e) { e.printStackTrace(); } finally { this.hasNotified = false; this.onWaitEnd(); } } } protected void onWaitEnd() { } public boolean isStoped() { return stoped; } public long getJointime() { return JoinTime; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/exception/ConnectFailedException.java ================================================ /* * Copyright (c) 2015 The Jupiter Project * * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.lyncc.netty.production.common.exception; /** * jupiter * org.jupiter.transport.exception * * @author jiachun.fjc */ public class ConnectFailedException extends RuntimeException { private static final long serialVersionUID = -2890742743547564900L; public ConnectFailedException() { super(); } public ConnectFailedException(String message) { super(message); } public ConnectFailedException(String message, Throwable cause) { super(message, cause); } public ConnectFailedException(Throwable cause) { super(cause); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/common/package-info.java ================================================ /** * @author BazingaLyn * @description 一些用的基本类 * @time 2016年7月20日16:50:10 * @modifytime */ package com.lyncc.netty.production.common; ================================================ FILE: src/main/java/com/lyncc/netty/production/example/ClientConnectorStartup.java ================================================ package com.lyncc.netty.production.example; import static com.lyncc.netty.production.common.NettyCommonProtocol.REQUEST; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lyncc.netty.production.client.connector.DefaultCommonClientConnector; import com.lyncc.netty.production.client.connector.DefaultCommonClientConnector.MessageNonAck; import com.lyncc.netty.production.common.Message; import com.lyncc.netty.production.srv.acceptor.DefaultCommonSrvAcceptor; /** * * @author BazingaLyn * @description 客户链接端 启动类 * @time 2016年7月22日14:53:32 * @modifytime */ public class ClientConnectorStartup { private static final Logger logger = LoggerFactory.getLogger(DefaultCommonSrvAcceptor.class); public static void main(String[] args) { DefaultCommonClientConnector clientConnector = new DefaultCommonClientConnector(); Channel channel = clientConnector.connect(20011, "127.0.0.1"); User user = new User(1, "dubbo"); Message message = new Message(); message.sign(REQUEST); message.data(user); //获取到channel发送双方规定的message格式的信息 channel.writeAndFlush(message).addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if(!future.isSuccess()) { logger.info("send fail,reason is {}",future.cause().getMessage()); } } }); //防止对象处理发生异常的情况 MessageNonAck msgNonAck = new MessageNonAck(message, channel); clientConnector.addNeedAckMessageInfo(msgNonAck); } public static class User { private Integer id; private String username; public User(Integer id, String username) { this.id = id; this.username = username; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User [id=" + id + ", username=" + username + "]"; } } } ================================================ FILE: src/main/java/com/lyncc/netty/production/example/SrvAcceptorStartup.java ================================================ package com.lyncc.netty.production.example; import com.lyncc.netty.production.srv.acceptor.DefaultCommonSrvAcceptor; public class SrvAcceptorStartup { public static void main(String[] args) throws InterruptedException { DefaultCommonSrvAcceptor defaultCommonSrvAcceptor = new DefaultCommonSrvAcceptor(20011,null); defaultCommonSrvAcceptor.start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/example/package-info.java ================================================ /** * */ /** * @author BazingaLyn * @description 测试包 * @time 2016年7月27日08:58:55 * @modifytime */ package com.lyncc.netty.production.example; ================================================ FILE: src/main/java/com/lyncc/netty/production/serializer/Serializer.java ================================================ package com.lyncc.netty.production.serializer; /** * * @author BazingaLyn * @description 序列化工具接口 * @time 2016年7月26日18:53:48 * @modifytime */ public interface Serializer { /** * 将obj序列化成byte数组 * @param obj * @return */ byte[] writeObject(T obj); /** * 将byte数组反序列化成class是clazz的obj对象 * @param bytes * @param clazz * @return */ T readObject(byte[] bytes, Class clazz); } ================================================ FILE: src/main/java/com/lyncc/netty/production/serializer/SerializerHolder.java ================================================ package com.lyncc.netty.production.serializer; import com.lyncc.netty.production.serializer.protostuff.ProtoStuffSerializer; /** * * @author BazingaLyn * @description 序列化工具 obj to byte 用于网络传输 * @time 2016年7月26日18:51:43 * @modifytime */ public final class SerializerHolder { //使用google的protostuff //protostuff 是一个支持各种格式的一个序列化Java类库,包括 JSON、XML、YAML等格式。 private static final Serializer serializer = new ProtoStuffSerializer(); public static Serializer serializerImpl() { return serializer; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/serializer/protostuff/ProtoStuffSerializer.java ================================================ package com.lyncc.netty.production.serializer.protostuff; import io.protostuff.LinkedBuffer; import io.protostuff.ProtostuffIOUtil; import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.objenesis.Objenesis; import org.objenesis.ObjenesisStd; import com.lyncc.netty.production.serializer.Serializer; /** * 具体实现 * @author BazingaLyn * @description * @time 2016年7月26日18:55:54 * @modifytime */ public class ProtoStuffSerializer implements Serializer { private static Map, Schema> cachedSchema = new ConcurrentHashMap, Schema>(); private static Objenesis objenesis = new ObjenesisStd(true); @SuppressWarnings("unchecked") public byte[] writeObject(T obj) { Class cls = (Class) obj.getClass(); LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { Schema schema = getSchema(cls); return ProtostuffIOUtil.toByteArray(obj, schema, buffer); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } finally { buffer.clear(); } } public T readObject(byte[] bytes, Class clazz) { try { T message = objenesis.newInstance(clazz); Schema schema = getSchema(clazz); ProtostuffIOUtil.mergeFrom(bytes, message, schema); return message; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } @SuppressWarnings("unchecked") private static Schema getSchema(Class cls) { Schema schema = (Schema) cachedSchema.get(cls); if (schema == null) { schema = RuntimeSchema.createFrom(cls); cachedSchema.put(cls, schema); } return schema; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/AcceptorIdleStateTrigger.java ================================================ package com.lyncc.netty.production.srv.acceptor; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author BazingaLyn * @description * @time * @modifytime 2016年7月21日09:39:22 */ @ChannelHandler.Sharable public class AcceptorIdleStateTrigger extends ChannelInboundHandlerAdapter { private static final Logger logger = LoggerFactory.getLogger(AcceptorIdleStateTrigger.class); @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState state = ((IdleStateEvent) evt).state(); if (state == IdleState.READER_IDLE) { logger.error("occor exception"); throw new Exception("NO SIGNAL"); } } else { super.userEventTriggered(ctx, evt); } } } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/AcknowledgeEncoder.java ================================================ package com.lyncc.netty.production.srv.acceptor; import static com.lyncc.netty.production.common.NettyCommonProtocol.ACK; import static com.lyncc.netty.production.common.NettyCommonProtocol.MAGIC; import static com.lyncc.netty.production.serializer.SerializerHolder.serializerImpl; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import com.lyncc.netty.production.common.Acknowledge; /** * * @author BazingaLyn * @description ack的编码器 * @time * @modifytime */ @ChannelHandler.Sharable public class AcknowledgeEncoder extends MessageToByteEncoder { @Override protected void encode(ChannelHandlerContext ctx, Acknowledge ack, ByteBuf out) throws Exception { byte[] bytes = serializerImpl().writeObject(ack); out.writeShort(MAGIC) .writeByte(ACK) .writeByte(0) .writeLong(ack.sequence()) .writeInt(bytes.length) .writeBytes(bytes); } } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/ChannelEventListener.java ================================================ package com.lyncc.netty.production.srv.acceptor; import io.netty.channel.Channel; public interface ChannelEventListener { void onChannelConnect(final String remoteAddr, final Channel channel); void onChannelClose(final String remoteAddr, final Channel channel); void onChannelException(final String remoteAddr, final Channel channel); void onChannelIdle(final String remoteAddr, final Channel channel); } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/DefaultCommonSrvAcceptor.java ================================================ package com.lyncc.netty.production.srv.acceptor; import static com.lyncc.netty.production.common.NettyCommonProtocol.HEARTBEAT; import static com.lyncc.netty.production.common.NettyCommonProtocol.MAGIC; import static com.lyncc.netty.production.common.NettyCommonProtocol.REQUEST; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_1; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_2; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_3; import static com.lyncc.netty.production.common.NettyCommonProtocol.SERVICE_4; import static com.lyncc.netty.production.serializer.SerializerHolder.serializerImpl; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.timeout.IdleStateHandler; import io.netty.util.Signal; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.List; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lyncc.netty.production.common.Acknowledge; import com.lyncc.netty.production.common.Message; import com.lyncc.netty.production.common.NativeSupport; import com.lyncc.netty.production.common.NettyCommonProtocol; import com.lyncc.netty.production.common.NettyEvent; import com.lyncc.netty.production.common.NettyEventType; /** * * @author BazingaLyn * @description 基本的常用的netty Server配置 * @time 2016年7月20日20:49:53 * @modifytime */ public class DefaultCommonSrvAcceptor extends DefaultSrvAcceptor { private static final Logger logger = LoggerFactory.getLogger(DefaultCommonSrvAcceptor.class); //acceptor的trigger private final AcceptorIdleStateTrigger idleStateTrigger = new AcceptorIdleStateTrigger(); //message的编码器 private final MessageEncoder encoder = new MessageEncoder(); //Ack的编码器 private final AcknowledgeEncoder ackEncoder = new AcknowledgeEncoder(); //SimpleChannelInboundHandler类型的handler只处理@{link Message}类型的数据 private final MessageHandler handler = new MessageHandler(); private final ChannelEventListener channelEventListener; public DefaultCommonSrvAcceptor(int port,ChannelEventListener channelEventListener) { super(new InetSocketAddress(port)); this.init(); this.channelEventListener = channelEventListener; } @Override protected void init() { super.init(); /** * backlog参数的含义: * 一个未完成连接的队列,此队列维护着那些已收到了客户端SYN分节信息,等待完成三路握手的连接,socket的状态是SYN_RCVD * .一个已完成的连接的队列,此队列包含了那些已经完成三路握手的连接,socket的状态是ESTABLISHED * backlog参数历史上被定义为上面两个队列的大小之和 * 当客户端的第一个SYN到达的时候,TCP会在未完成队列中增加一个新的记录然后回复给客户端三路握手中的第二个分节(服务端的SYN和针对客户端的ACK) * ,这条记录会在未完成队列中一直存在,直到三路握手中的最后一个分节到达,或者直到超时(Berkeley时间将这个超时定义为75秒) * 如果当客户端SYN到达的时候队列已满,TCP将会忽略后续到达的SYN,但是不会给客户端发送RST信息,因为此时允许客户端重传SYN分节,如果返回错误 * 信息,那么客户端将无法分清到底是服务端对应端口上没有相应应用程序还是服务端对应端口上队列已满这两种情况 */ bootstrap().option(ChannelOption.SO_BACKLOG, 32768) /** * [TCP/IP协议详解]中描述: * 当TCP执行一个主动关闭, 并发回最后一个ACK ,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL. * 这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN). * 这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间, 定义这个连接的插口对(TCP四元组)不能再被使用. * 这个连接只能在2MSL结束后才能再被使用. * * 许多具体的实现中允许一个进程重新使用仍处于2MSL等待的端口(通常是设置选项SO_REUSEADDR), * 但TCP不能允许一个新的连接建立在相同的插口对上。 */ .option(ChannelOption.SO_REUSEADDR, true) // .childOption(ChannelOption.SO_REUSEADDR, true) /** * 为TCP套接字设置keepalive选项时, 如果在2个小时(实际值与具体实现有关)内在 * 任意方向上都没有跨越套接字交换数据, 则 TCP 会自动将 keepalive 探头发送到对端. * 此探头是对端必须响应的TCP段. * * 期望的响应为以下三种之一: * 1. 收到期望的对端ACK响应 * 不通知应用程序(因为一切正常), 在另一个2小时的不活动时间过后,TCP将发送另一个探头。 * 2. 对端响应RST * 通知本地TCP对端已崩溃并重新启动, 套接字被关闭. * 3. 对端没有响 * 套接字被关闭。 * * 此选项的目的是检测对端主机是否崩溃, 仅对TCP套接字有效. */ .childOption(ChannelOption.SO_KEEPALIVE, true) /** * 对此连接禁用 Nagle 算法. * 在确认以前的写入数据之前不会缓冲写入网络的数据. 仅对TCP有效. * * Nagle算法试图减少TCP包的数量和结构性开销, 将多个较小的包组合成较大的包进行发送. * 但这不是重点, 关键是这个算法受TCP延迟确认影响, 会导致相继两次向连接发送请求包, * 读数据时会有一个最多达500毫秒的延时. * * 这叫做“ACK delay”, 解决办法是设置TCP_NODELAY。 */ .childOption(ChannelOption.TCP_NODELAY, true) /** * 禁用掉半关闭的状态的链接状态 * TCP四次握手关闭连接的时候,step2-step3中出现的状态 */ .childOption(ChannelOption.ALLOW_HALF_CLOSURE, false); } @Override protected EventLoopGroup initEventLoopGroup(int nthread, ThreadFactory bossFactory) { return NativeSupport.isSupportNativeET() ? new EpollEventLoopGroup(nthread, bossFactory) : new NioEventLoopGroup(nthread, bossFactory); } @Override protected ChannelFuture bind(SocketAddress localAddress) { ServerBootstrap boot = bootstrap(); boot.channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( //每隔60s的时间内如果没有接受到任何的read事件的话,则会触发userEventTriggered事件,并指定IdleState的类型为READER_IDLE new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS), //因为我们在client端设置了每隔30s会发送一个心跳包过来,如果60s都没有收到心跳,则说明链路发生了问题 idleStateTrigger, //message的解码器 new MessageDecoder(), encoder, ackEncoder, new NettyConnetManageHandler(), handler); } }); return boot.bind(localAddress); } /** * 解码器,继承于ReplayingDecoder * @author BazingaLyn * @description * @time * @modifytime */ /** * ************************************************************************************************** * Protocol * ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ * 2 │ 1 │ 1 │ 8 │ 4 │ * ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ * │ │ │ │ │ * │ MAGIC Sign Status Invoke Id Body Length Body Content │ * │ │ │ │ │ * └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ * * 消息头16个字节定长 * = 2 // MAGIC = (short) 0xbabe * + 1 // 消息标志位, 用来表示消息类型 * + 1 // 空 * + 8 // 消息 id long 类型 * + 4 // 消息体body长度, int类型 */ static class MessageDecoder extends ReplayingDecoder { //构造函数 设置初始的枚举类型是什么 public MessageDecoder() { super(State.HEADER_MAGIC); } // 协议头 private final NettyCommonProtocol header = new NettyCommonProtocol(); @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { switch (state()) { case HEADER_MAGIC: checkMagic(in.readShort()); // MAGIC checkpoint(State.HEADER_SIGN); case HEADER_SIGN: header.sign(in.readByte()); // 消息标志位 checkpoint(State.HEADER_STATUS); case HEADER_STATUS: in.readByte(); // no-op checkpoint(State.HEADER_ID); case HEADER_ID: header.id(in.readLong()); // 消息id checkpoint(State.HEADER_BODY_LENGTH); case HEADER_BODY_LENGTH: header.bodyLength(in.readInt()); // 消息体长度 checkpoint(State.BODY); case BODY: switch (header.sign()) { case HEARTBEAT: break; case REQUEST: case SERVICE_1: case SERVICE_2: case SERVICE_3: case SERVICE_4: { byte[] bytes = new byte[header.bodyLength()]; in.readBytes(bytes); Message msg = serializerImpl().readObject(bytes, Message.class); msg.sign(header.sign()); out.add(msg); break; } default: throw new IllegalAccessException(); } checkpoint(State.HEADER_MAGIC); } } private static void checkMagic(short magic) throws Signal { if (MAGIC != magic) { throw new IllegalArgumentException(); } } enum State { HEADER_MAGIC, HEADER_SIGN, HEADER_STATUS, HEADER_ID, HEADER_BODY_LENGTH, BODY } } /** * ************************************************************************************************** * Protocol * ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ * 2 │ 1 │ 1 │ 8 │ 4 │ * ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ * │ │ │ │ │ * │ MAGIC Sign Status Invoke Id Body Length Body Content │ * │ │ │ │ │ * └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ * * 消息头16个字节定长 * = 2 // MAGIC = (short) 0xbabe * + 1 // 消息标志位, 用来表示消息类型 * + 1 // 空 * + 8 // 消息 id long 类型 * + 4 // 消息体body长度, int类型 */ @ChannelHandler.Sharable static class MessageEncoder extends MessageToByteEncoder { @Override protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception { byte[] bytes = serializerImpl().writeObject(msg); out.writeShort(MAGIC) .writeByte(msg.sign()) .writeByte(0) .writeLong(0) .writeInt(bytes.length) .writeBytes(bytes); } } @ChannelHandler.Sharable class MessageHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Message message) throws Exception { Channel channel = ctx.channel(); logger.info(message.toString()); // 接收到发布信息的时候,要给Client端回复ACK channel.writeAndFlush(new Acknowledge(message.sequence())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); } } class NettyConnetManageHandler extends ChannelDuplexHandler { @Override public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise future) throws Exception { final String local = localAddress == null ? "UNKNOW" : localAddress.toString(); final String remote = remoteAddress == null ? "UNKNOW" : remoteAddress.toString(); logger.info("NETTY CLIENT PIPELINE: CONNECT {} => {}", local, remote); super.connect(ctx, remoteAddress, localAddress, future); if (DefaultCommonSrvAcceptor.this.channelEventListener != null) { DefaultCommonSrvAcceptor.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress .toString(), ctx.channel())); } } @Override public void disconnect(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { final String remoteAddress = ctx.channel().remoteAddress().toString(); logger.info("NETTY CLIENT PIPELINE: DISCONNECT {}", remoteAddress); super.disconnect(ctx, future); if (DefaultCommonSrvAcceptor.this.channelEventListener != null) { DefaultCommonSrvAcceptor.this.putNettyEvent(new NettyEvent(NettyEventType.CLOSE, remoteAddress .toString(), ctx.channel())); } } @Override public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { final String remoteAddress = ctx.channel().remoteAddress().toString(); logger.info("NETTY CLIENT PIPELINE: CLOSE {}", remoteAddress); super.close(ctx, promise); if (DefaultCommonSrvAcceptor.this.channelEventListener != null) { DefaultCommonSrvAcceptor.this.putNettyEvent(new NettyEvent(NettyEventType.CLOSE, remoteAddress .toString(), ctx.channel())); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { final String remoteAddress = ctx.channel().remoteAddress().toString(); logger.warn("NETTY CLIENT PIPELINE: exceptionCaught {}", remoteAddress); logger.warn("NETTY CLIENT PIPELINE: exceptionCaught exception.", cause); if (DefaultCommonSrvAcceptor.this.channelEventListener != null) { DefaultCommonSrvAcceptor.this.putNettyEvent(new NettyEvent(NettyEventType.EXCEPTION, remoteAddress .toString(), ctx.channel())); } } } @Override protected ChannelEventListener getChannelEventListener() { return channelEventListener; } } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/DefaultSrvAcceptor.java ================================================ package com.lyncc.netty.production.srv.acceptor; import java.net.SocketAddress; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lyncc.netty.production.common.NettyEvent; import com.lyncc.netty.production.common.ServiceThread; public abstract class DefaultSrvAcceptor extends NettySrvAcceptor { private static final Logger logger = LoggerFactory.getLogger(DefaultCommonSrvAcceptor.class); protected final NettyEventExecuter nettyEventExecuter = new NettyEventExecuter(); public void putNettyEvent(final NettyEvent event) { this.nettyEventExecuter.putNettyEvent(event); } public DefaultSrvAcceptor(SocketAddress localAddress) { super(localAddress); } class NettyEventExecuter extends ServiceThread { private final LinkedBlockingQueue eventQueue = new LinkedBlockingQueue(); private final int MaxSize = 10000; public void putNettyEvent(final NettyEvent event) { if (this.eventQueue.size() <= MaxSize) { this.eventQueue.add(event); } else { logger.warn("event queue size[{}] enough, so drop this event {}", this.eventQueue.size(), event.toString()); } } public void run() { logger.info(this.getServiceName() + " service started"); final ChannelEventListener listener = DefaultSrvAcceptor.this.getChannelEventListener(); while (!this.isStoped()) { try { NettyEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS); if (event != null && listener != null) { switch (event.getType()) { case IDLE: listener.onChannelIdle(event.getRemoteAddr(), event.getChannel()); break; case CLOSE: listener.onChannelClose(event.getRemoteAddr(), event.getChannel()); break; case CONNECT: listener.onChannelConnect(event.getRemoteAddr(), event.getChannel()); break; case EXCEPTION: listener.onChannelException(event.getRemoteAddr(), event.getChannel()); break; default: break; } } } catch (Exception e) { logger.warn(this.getServiceName() + " service has exception. ", e); } } logger.info(this.getServiceName() + " service end"); } @Override public String getServiceName() { return NettyEventExecuter.class.getSimpleName(); } } protected abstract ChannelEventListener getChannelEventListener(); } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/NettySrvAcceptor.java ================================================ package com.lyncc.netty.production.srv.acceptor; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.internal.PlatformDependent; import java.net.SocketAddress; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author BazingaLyn * @description Netty Server接收端的{@link ServerBootstrap}的初始化和Netty的一些启动参数 * @time 2016年7月20日19:56:45 * @modifytime */ public abstract class NettySrvAcceptor implements SrvAcceptor { private static final Logger logger = LoggerFactory.getLogger(NettySrvAcceptor.class); public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors(); protected final SocketAddress localAddress; //netty base element private ServerBootstrap bootstrap; private EventLoopGroup boss; private EventLoopGroup worker; private int nWorkers; protected volatile ByteBufAllocator allocator; protected final HashedWheelTimer timer = new HashedWheelTimer(new ThreadFactory() { private AtomicInteger threadIndex = new AtomicInteger(0); public Thread newThread(Runnable runnable) { return new Thread(runnable, "NettySrvAcceptorExecutor_" + this.threadIndex.incrementAndGet()); } }); public NettySrvAcceptor(SocketAddress localAddress) { this(localAddress, AVAILABLE_PROCESSORS << 1); } public NettySrvAcceptor(SocketAddress localAddress, int nWorkers) { this.localAddress = localAddress; this.nWorkers = nWorkers; } //netty的元素初始化 protected void init(){ ThreadFactory bossFactory = new DefaultThreadFactory("netty.acceptor.boss"); ThreadFactory workerFactory = new DefaultThreadFactory("netty.acceptor.worker"); boss = initEventLoopGroup(1, bossFactory); worker = initEventLoopGroup(nWorkers, workerFactory); //使用池化的directBuffer /** * 一般高性能的场景下,使用的堆外内存,也就是直接内存,使用堆外内存的好处就是减少内存的拷贝,和上下文的切换,缺点是 * 堆外内存处理的不好容易发生堆外内存OOM * 当然也要看当前的JVM是否只是使用堆外内存,换而言之就是是否能够获取到Unsafe对象#PlatformDependent.directBufferPreferred() */ allocator = new PooledByteBufAllocator(PlatformDependent.directBufferPreferred()); //create && group bootstrap= new ServerBootstrap().group(worker, worker); //ByteBufAllocator 配置 bootstrap.childOption(ChannelOption.ALLOCATOR, allocator); } public void start() throws InterruptedException { this.start(true); } public void start(boolean sync) throws InterruptedException { ChannelFuture future = bind(localAddress).sync(); logger.info("netty acceptor server start"); if (sync) { future.channel().closeFuture().sync(); } } public SocketAddress localAddress() { return localAddress; } protected ServerBootstrap bootstrap() { return bootstrap; } public void shutdownGracefully() { boss.shutdownGracefully().awaitUninterruptibly(); worker.shutdownGracefully().awaitUninterruptibly(); } protected abstract EventLoopGroup initEventLoopGroup(int nthread, ThreadFactory bossFactory); protected abstract ChannelFuture bind(SocketAddress localAddress); } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/SrvAcceptor.java ================================================ package com.lyncc.netty.production.srv.acceptor; import java.net.SocketAddress; /** * * @author BazingaLyn * @description netty server端的标准接口定义 * @time 2016年7月20日16:41:04 * @modifytime */ public interface SrvAcceptor { SocketAddress localAddress(); void start() throws InterruptedException; void shutdownGracefully(); void start(boolean sync) throws InterruptedException; } ================================================ FILE: src/main/java/com/lyncc/netty/production/srv/acceptor/package-info.java ================================================ /** * @author BazingaLyn * netty生成级别的server/client端的模板代码 * * 不一定任何场合都适用,但是自我感觉是一种比较规范的写法 * * 参考 RPC框架 Jupiter https://github.com/fengjiachun/Jupiter * RocketMQ https://github.com/alibaba/RocketMQ * @time 2016年7月20日16:06:26 */ package com.lyncc.netty.production.srv.acceptor; ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/correct/BaseClient.java ================================================ package com.lyncc.netty.stickpackage.correct; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new BaseClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/correct/BaseClientHandler.java ================================================ package com.lyncc.netty.stickpackage.correct; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * * @author bazingaLyncc * 描述:客户端的第一个自定义的inbound处理器 * 时间 2016年5月3日 */ public class BaseClientHandler extends ChannelInboundHandlerAdapter{ private byte[] req; private int counter; public BaseClientHandler() { req = ("QUERY TIME ORDER" + System.getProperty("line.separator")) .getBytes(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ByteBuf message = null; for (int i = 0; i < 100; i++) { message = Unpooled.buffer(req.length); message.writeBytes(req); ctx.writeAndFlush(message); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, "UTF-8"); System.out.println("Now is : " + body + " ; the counter is : "+ ++counter); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/correct/BaseServer.java ================================================ package com.lyncc.netty.stickpackage.correct; 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 java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/correct/BaseServerHandler.java ================================================ package com.lyncc.netty.stickpackage.correct; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ private int counter; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf)msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, CharsetUtil.UTF_8).substring(0, req.length - System.getProperty("line.separator").length()); System.out.println("server receive order : " + body + ";the counter is: " + ++counter); String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date( System.currentTimeMillis()).toString() : "BAD ORDER"; currentTime = currentTime + System.getProperty("line.separator"); ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); ctx.writeAndFlush(resp); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/delimiter/BaseClient.java ================================================ package com.lyncc.netty.stickpackage.delimiter; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); ChannelPipeline p = ch.pipeline(); p.addLast(new DelimiterBasedFrameDecoder(1024,delimiter)); p.addLast(new StringDecoder()); p.addLast(new BaseClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/delimiter/BaseClientHandler.java ================================================ package com.lyncc.netty.stickpackage.delimiter; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * * @author bazingaLyncc * 描述:客户端的第一个自定义的inbound处理器 * 时间 2016年5月3日 */ public class BaseClientHandler extends ChannelInboundHandlerAdapter{ private int counter; static final String FIXED_REQ = "Hi,Lyncc,Learn English.$_"; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 100; i++) { ctx.writeAndFlush(Unpooled.copiedBuffer(FIXED_REQ.getBytes())); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Now is : " + msg + " ; the counter is : "+ ++counter); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/delimiter/BaseServer.java ================================================ package com.lyncc.netty.stickpackage.delimiter; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; 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.DelimiterBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; import java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); ChannelPipeline p = ch.pipeline(); p.addLast(new DelimiterBasedFrameDecoder(1024,delimiter)); p.addLast(new StringDecoder()); p.addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/delimiter/BaseServerHandler.java ================================================ package com.lyncc.netty.stickpackage.delimiter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ private int counter; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println(msg + " the counter is " + ++counter); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/error/BaseClient.java ================================================ package com.lyncc.netty.stickpackage.error; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new LineBasedFrameDecoder(1024)); p.addLast(new StringDecoder()); p.addLast(new BaseClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/error/BaseClientHandler.java ================================================ package com.lyncc.netty.stickpackage.error; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * * @author bazingaLyncc * 描述:客户端的第一个自定义的inbound处理器 * 时间 2016年5月3日 */ public class BaseClientHandler extends ChannelInboundHandlerAdapter{ private byte[] req; private int counter; public BaseClientHandler() { req = ("QUERY TIME ORDER" + System.getProperty("line.separator")) .getBytes(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ByteBuf message = null; for (int i = 0; i < 100; i++) { message = Unpooled.buffer(req.length); message.writeBytes(req); ctx.writeAndFlush(message); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String buf = (String) msg; System.out.println("Now is : " + buf + " ; the counter is : "+ ++counter); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/error/BaseServer.java ================================================ package com.lyncc.netty.stickpackage.error; 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.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; import java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new LineBasedFrameDecoder(1024)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/error/BaseServerHandler.java ================================================ package com.lyncc.netty.stickpackage.error; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ private int counter; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String)msg; System.out.println("server receive order : " + body + ";the counter is: " + ++counter); String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date( System.currentTimeMillis()).toString() : "BAD ORDER"; currentTime = currentTime + System.getProperty("line.separator"); ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); ctx.writeAndFlush(resp); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/myself/BaseClient.java ================================================ package com.lyncc.netty.stickpackage.myself; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; public class BaseClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY,true) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); // p.addLast(new LineBasedFrameDecoder(1024)); p.addLast(new StringDecoder()); p.addLast(new BaseClientHandler()); } }); ChannelFuture future = b.connect(HOST, PORT).sync(); future.channel().writeAndFlush("Hello Netty Server ,I am a common client"); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/myself/BaseClientHandler.java ================================================ package com.lyncc.netty.stickpackage.myself; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class BaseClientHandler extends ChannelInboundHandlerAdapter{ private byte[] req; public BaseClientHandler() { // req = ("BazingaLyncc is learner").getBytes(); req = ("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. $$__ His book w" + "ill give We’ve reached an exciting point—in the next chapter we’ll $$__ discuss bootstrapping, the process " + "of configuring and connecting all of Netty’s components to bring $$__ your learned about threading models in ge" + "neral and Netty’s threading model in particular, whose performance $$__ and consistency advantages we discuss" + "ed in detail In this chapter you general, we recommend Java $$__Concurrency in Practice by Brian Goetz. Hi" + "s book will give We’ve reached an exciting point—in the next $$__ chapter we’ll discuss bootstrapping, the" + " process of configuring and connecting all of Netty’s components $$__ to bring your learned about threading " + "models in general and Netty’s threading model in particular, $$__ whose performance and consistency advantag" + "es we discussed in detailIn this chapter you general, $$__ we recommend Java Concurrency in Practice by Bri" + "an Goetz. His book will give We’ve reached an exciting $$__ point—in the next chapter;the counter is: 1 2222" + "sdsa ddasd asdsadas dsadasdas" + System.getProperty("line.separator")).getBytes(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ByteBuf message = null; // for (int i = 0; i < 100; i++) { // message = Unpooled.buffer(req.length); // message.writeBytes(req); // ctx.writeAndFlush(message); // } message = Unpooled.buffer(req.length); message.writeBytes(req); ctx.writeAndFlush(message); message = Unpooled.buffer(req.length); message.writeBytes(req); ctx.writeAndFlush(message); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/myself/BaseServer.java ================================================ package com.lyncc.netty.stickpackage.myself; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.Unpooled; 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.DelimiterBasedFrameDecoder; import io.netty.handler.codec.FixedLengthFrameDecoder; import io.netty.handler.codec.string.StringDecoder; import java.net.InetSocketAddress; public class BaseServer { private int port; public BaseServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer() { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,Unpooled.copiedBuffer("$$__".getBytes()))); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new BaseServerHandler()); }; }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture future = sbs.bind(port).sync(); System.out.println("Server start listen at " + port ); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new BaseServer(port).start(); } } ================================================ FILE: src/main/java/com/lyncc/netty/stickpackage/myself/BaseServerHandler.java ================================================ package com.lyncc.netty.stickpackage.myself; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class BaseServerHandler extends ChannelInboundHandlerAdapter{ private int counter; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String)msg; System.out.println("server receive order : " + body + ";the counter is: " + ++counter); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ================================================ FILE: src/main/resources/logback.xml ================================================ %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%logger{0}] - %msg%n 65536