1、数据结构定义

  1)netty消息:NettyMessage

    

 package com.cherry.netty.demo.protocolstack.pojo;

 import com.cherry.netty.utils.JsonUtil;

 public final class NettyMessage {
private Header header;
private Object body;
public final Header getHeader() {
return header;
}
public final void setHeader(Header header) {
this.header = header;
}
public final Object getBody() {
return body;
}
public final void setBody(Object body) {
this.body = body;
}
@Override
public String toString() {
return "NettyMessage[header="+JsonUtil.toJson(header)+"]";
} }

  2)消息头:Header

 package com.cherry.netty.demo.protocolstack.pojo;

 import java.util.HashMap;
import java.util.Map; import com.cherry.netty.utils.JsonUtil; public final class Header {
private int crcCode = 0Xabef0101;
private int length;
private long sessionID;
private byte type;
private byte priority;
private Map<String, Object> attachment = new HashMap<String,Object>();
public final int getCrcCode() {
return crcCode;
}
public final void setCrcCode(int crcCode) {
this.crcCode = crcCode;
}
public final int getLength() {
return length;
}
public final void setLength(int length) {
this.length = length;
}
public final long getSessionID() {
return sessionID;
}
public final void setSessionID(long sessionID) {
this.sessionID = sessionID;
}
public final byte getType() {
return type;
}
public final void setType(byte type) {
this.type = type;
}
public final byte getPriority() {
return priority;
}
public final void setPriority(byte priority) {
this.priority = priority;
}
public final Map<String, Object> getAttachment() {
return attachment;
}
public final void setAttachment(Map<String, Object> attachment) {
this.attachment = attachment;
}
@Override
public String toString() {
return "Header:"+JsonUtil.toJson(this);
} }

另补充MessageType、NettyConstant

 package com.cherry.netty.demo.protocolstack.pojo;

 public enum MessageType {
LOGIN_REQ((byte) 1), LOGIN_RESP((byte) 2), HEARTBEAT_REQ((byte) 3), HEARTBEAT_RESP((byte) 4),; public byte value; MessageType(byte v) {
this.value = v;
} public byte value() {
return value;
} }
 package com.cherry.netty.demo.protocolstack.pojo;

 public final class NettyConstant {

     public static String LOCALIP = "127.0.0.1";
public static Integer LOCAL_PORT = 9090;
public static String REMOTEIP = "127.0.0.1";
public static Integer REMOTE_PORT = 8080; }

2、消息编解码

① pom.xml文件。学习期间 org.jboss.marshalling的2.0.6.Final创建channel会异常。

WARN io.netty.channel.ChannelInitializer - Failed to initialize a channel. Closing: [id: 0xd6032f4c]
java.util.ServiceConfigurationError: org.jboss.marshalling.ProviderDescriptor: Provider org.jboss.marshalling.serial.SerialProviderDescriptor not found

将jboss-marshalling和jboss-marshalling-serial的版本号更新为小于2.0.6的即可。

 <?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>netty</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>netty-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>netty-demo</name>
<url>http://maven.apache.org</url> <packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency> <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.6.1</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jibx/jibx-run -->
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-run</artifactId>
<version>1.3.1</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jibx/jibx-tools -->
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-tools</artifactId>
<version>1.3.1</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<!-- <version>1.4.10.Final</version> -->
<version>2.0.3.Final</version>
</dependency> <dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-serial</artifactId>
<!-- <version>1.4.10.Final</version> -->
<version>2.0.3.Final</version>
</dependency> </dependencies> <build>
<pluginManagement>
<plugins>
<plugin>
<!-- 生成jibx class信息 -->
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<schemaBindingDirectory>${basedir}/target/classes/jibx</schemaBindingDirectory>
<includeSchemaBindings>
<includeSchemaBindings>*binding.xml</includeSchemaBindings>
</includeSchemaBindings>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<id>jibx-bind</id>
<!-- 把jibx绑定到了comile编译阶段 -->
<phase>compile</phase>
<goals>
<goal>bind</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build> </project>

②MarshallingCodeCFactory

 package com.cherry.netty.demo.protocolstack.utils;

 import java.io.IOException;

 import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.marshalling.Unmarshaller; public final class MarshallingCodeCFactory { public static Marshaller buildMarshalling() throws IOException {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
Marshaller marshaller = marshallerFactory.createMarshaller(configuration);
return marshaller;
} public static Unmarshaller buildUnMarshalling() throws IOException {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
final Unmarshaller unmarshaller = marshallerFactory.createUnmarshaller(configuration);
return unmarshaller;
} }

③NettyMessageEncoder、MarshallingEncoder、ChannelBufferByteOutput

 package com.cherry.netty.demo.protocolstack.encode;

 import java.io.IOException;
import java.util.Map; import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder; public final class NettyMessageEncoder extends MessageToByteEncoder<NettyMessage> {
MarshallingEncoder marshallingEncoder; public NettyMessageEncoder() throws IOException {
this.marshallingEncoder = new MarshallingEncoder();
} @SuppressWarnings("unused")
@Override
protected void encode(ChannelHandlerContext ctx, NettyMessage msg, ByteBuf sendBuf) throws Exception {
if (null == msg || null == msg.getHeader()) {
throw new Exception("The encode message is null");
}
sendBuf.writeInt(msg.getHeader().getCrcCode());
sendBuf.writeInt(msg.getHeader().getLength());
sendBuf.writeLong(msg.getHeader().getSessionID());
sendBuf.writeByte(msg.getHeader().getType());
sendBuf.writeByte(msg.getHeader().getPriority());
sendBuf.writeInt(msg.getHeader().getAttachment().size()); String key = null;
byte[] keyArray = null;
Object value = null;
for (Map.Entry<String, Object> param : msg.getHeader().getAttachment()
.entrySet()) {
key = param.getKey();
keyArray = key.getBytes("UTF-8");
sendBuf.writeInt(keyArray.length);
sendBuf.writeBytes(keyArray);
value = param.getValue();
}
key = null;
keyArray = null;
value = null; if (msg.getBody() != null) {
marshallingEncoder.encode(msg.getBody(), sendBuf);
} else{
sendBuf.writeInt(0);
}
         // 此处需要特别注意
sendBuf.setInt(4, sendBuf.readableBytes() - 8);
}
}
 package com.cherry.netty.demo.protocolstack.encode;

 import java.io.IOException;

 import org.jboss.marshalling.Marshaller;

 import com.cherry.netty.demo.protocolstack.utils.MarshallingCodeCFactory;

 import io.netty.buffer.ByteBuf;

 public class MarshallingEncoder {

     private static final byte[] LENGTH_PLACEHOLDER = new byte[4];

     Marshaller marshaller;

     public MarshallingEncoder() throws IOException {
marshaller = MarshallingCodeCFactory.buildMarshalling();
} protected void encode(Object msg, ByteBuf out) throws IOException {
try {
int lengthPos = out.writerIndex();
out.writeBytes(LENGTH_PLACEHOLDER);
ChannelBufferByteOutput output = new ChannelBufferByteOutput(out);
marshaller.start(output);
marshaller.writeObject(msg);
marshaller.finish();
out.setInt(lengthPos, out.writerIndex() - lengthPos - 4);
} finally {
marshaller.close();
}
} }
 package com.cherry.netty.demo.protocolstack.encode;

 import io.netty.buffer.ByteBuf;
import org.jboss.marshalling.ByteOutput; import java.io.IOException; class ChannelBufferByteOutput implements ByteOutput { private final ByteBuf buffer; public ChannelBufferByteOutput(ByteBuf buffer) {
this.buffer = buffer;
} @Override
public void close() throws IOException {
} @Override
public void flush() throws IOException {
} @Override
public void write(int b) throws IOException {
buffer.writeByte(b);
} @Override
public void write(byte[] bytes) throws IOException {
buffer.writeBytes(bytes);
} @Override
public void write(byte[] bytes, int srcIndex, int length) throws IOException {
buffer.writeBytes(bytes, srcIndex, length);
} ByteBuf getBuffer() {
return buffer;
}
}

④NettyMessageDecoder、MarshallingDecoder、ChannelBufferByteInput

 package com.cherry.netty.demo.protocolstack.decode;

 import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import com.cherry.netty.demo.protocolstack.pojo.Header;
import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder; public class NettyMessageDecoder extends LengthFieldBasedFrameDecoder {
MarshallingDecoder marshallingDecoder; public NettyMessageDecoder(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength) throws IOException {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
marshallingDecoder = new MarshallingDecoder();
} @Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in)
throws Exception {
ByteBuf frame = (ByteBuf) super.decode(ctx, in);
if (frame == null) {
return null;
} NettyMessage message = new NettyMessage();
Header header = new Header();
header.setCrcCode(frame.readInt());
header.setLength(frame.readInt());
header.setSessionID(frame.readLong());
header.setType(frame.readByte());
header.setPriority(frame.readByte()); int size = frame.readInt();
if (size > 0) {
Map<String, Object> attch = new HashMap<String, Object>(size);
int keySize = 0;
byte[] keyArray = null;
String key = null;
for (int i = 0; i < size; i++) {
keySize = frame.readInt();
keyArray = new byte[keySize];
frame.readBytes(keyArray);
key = new String(keyArray, "UTF-8");
attch.put(key, marshallingDecoder.decode(frame));
}
keyArray = null;
key = null;
header.setAttachment(attch);
}
if (frame.readableBytes() > 4) {
message.setBody(marshallingDecoder.decode(frame));
}
message.setHeader(header);
return message;
}
}
 package com.cherry.netty.demo.protocolstack.decode;

 import java.io.IOException;

 import org.jboss.marshalling.ByteInput;
import org.jboss.marshalling.Unmarshaller; import com.cherry.netty.demo.protocolstack.utils.MarshallingCodeCFactory; import io.netty.buffer.ByteBuf; public class MarshallingDecoder { private final Unmarshaller unmarshaller; public MarshallingDecoder() throws IOException {
unmarshaller = MarshallingCodeCFactory.buildUnMarshalling();
} protected Object decode(ByteBuf in) throws IOException, ClassNotFoundException {
int objectSize = in.readInt();
ByteBuf buf = in.slice(in.readerIndex(), objectSize);
ByteInput input = new ChannelBufferByteInput(buf);
try {
unmarshaller.start(input);
Object obj = unmarshaller.readObject();
unmarshaller.finish();
in.readerIndex(in.readerIndex() + objectSize);
return obj;
} finally {
unmarshaller.close();
}
} }
 package com.cherry.netty.demo.protocolstack.decode;

 import io.netty.buffer.ByteBuf;
import org.jboss.marshalling.ByteInput; import java.io.IOException; class ChannelBufferByteInput implements ByteInput { private final ByteBuf buffer; public ChannelBufferByteInput(ByteBuf buffer) {
this.buffer = buffer;
} @Override
public void close() throws IOException {
// nothing to do
} @Override
public int available() throws IOException {
return buffer.readableBytes();
} @Override
public int read() throws IOException {
if (buffer.isReadable()) {
return buffer.readByte() & 0xff;
}
return -1;
} @Override
public int read(byte[] array) throws IOException {
return read(array, 0, array.length);
} @Override
public int read(byte[] dst, int dstIndex, int length) throws IOException {
int available = available();
if (available == 0) {
return -1;
} length = Math.min(available, length);
buffer.readBytes(dst, dstIndex, length);
return length;
} @Override
public long skip(long bytes) throws IOException {
int readable = buffer.readableBytes();
if (readable < bytes) {
bytes = readable;
}
buffer.readerIndex((int) (buffer.readerIndex() + bytes));
return bytes;
} }

3、握手和安全认证

  

 package com.cherry.netty.demo.protocolstack.loginhandler;

 import org.apache.log4j.Logger;

 import com.cherry.netty.demo.protocolstack.pojo.Header;
import com.cherry.netty.demo.protocolstack.pojo.MessageType;
import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class LoginAuthReqHandler extends ChannelHandlerAdapter { private static final Logger logger = Logger.getLogger(LoginAuthReqHandler.class); @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(buildLoginReq());
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
NettyMessage message = (NettyMessage) msg; if (message.getHeader() != null
&& message.getHeader().getType() == MessageType.LOGIN_RESP.value()) {
byte loginResult = (byte) message.getBody();
if (loginResult != (byte) 0) {
ctx.close();
} else {
logger.info("Login is ok : " + message);
ctx.fireChannelRead(msg);
}
} else
ctx.fireChannelRead(msg);
} private NettyMessage buildLoginReq() {
NettyMessage message = new NettyMessage();
Header header = new Header();
header.setType(MessageType.LOGIN_REQ.value());
message.setHeader(header);
return message;
} public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.fireExceptionCaught(cause);
} }
 package com.cherry.netty.demo.protocolstack.loginhandler;

 import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import com.cherry.netty.demo.protocolstack.pojo.Header;
import com.cherry.netty.demo.protocolstack.pojo.MessageType;
import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class LoginAuthRespHandler extends ChannelHandlerAdapter { private static final Logger logger = Logger.getLogger(LoginAuthRespHandler.class); private Map<String, Boolean> nodeCheck = new ConcurrentHashMap<String, Boolean>();
private String[] whitekList = { "127.0.0.1", "192.168.11.246", "192.168.31.242" }; @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
NettyMessage message = (NettyMessage) msg; if (message.getHeader() != null && message.getHeader().getType() == MessageType.LOGIN_REQ.value()) {
String nodeIndex = ctx.channel().remoteAddress().toString();
NettyMessage loginResp = null;
// 重复登陆,拒绝
if (nodeCheck.containsKey(nodeIndex)) {
loginResp = buildResponse((byte) -1);
} else {
InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
String ip = address.getAddress().getHostAddress();
boolean isOK = false;
for (String WIP : whitekList) {
if (WIP.equals(ip)) {
isOK = true;
break;
}
}
loginResp = isOK ? buildResponse((byte) 0) : buildResponse((byte) -1);
if (isOK)
nodeCheck.put(nodeIndex, true);
}
logger.info("The login response is : " + loginResp + " body [" + loginResp.getBody() + "]");
ctx.writeAndFlush(loginResp);
} else {
ctx.fireChannelRead(msg);
}
} private NettyMessage buildResponse(byte result) {
NettyMessage message = new NettyMessage();
Header header = new Header();
header.setType(MessageType.LOGIN_RESP.value());
message.setHeader(header);
message.setBody(result);
return message;
} public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
nodeCheck.remove(ctx.channel().remoteAddress().toString());
ctx.close();
ctx.fireExceptionCaught(cause);
}
}

4、心跳检测机制

 package com.cherry.netty.demo.protocolstack.hearthandler;

 import java.util.concurrent.TimeUnit;

 import com.cherry.netty.demo.protocolstack.pojo.Header;
import com.cherry.netty.demo.protocolstack.pojo.MessageType;
import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.ScheduledFuture; public class HeartBeatReqHandler extends ChannelHandlerAdapter { private volatile ScheduledFuture<?> heartBeat; @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
NettyMessage message = (NettyMessage) msg;
if(message.getHeader() != null && message.getHeader().getType()==MessageType.LOGIN_RESP.value()){
heartBeat = ctx.executor().scheduleAtFixedRate(new HeartBeatReqHandler.HeartBeatTask(ctx), 0, 5000, TimeUnit.MILLISECONDS);
}else if(message.getHeader() !=null && message.getHeader().getType()==MessageType.HEARTBEAT_RESP.value()){
System.out.println("Client receive server heart beat message:---> "+message);
}else{
ctx.fireChannelRead(msg);
}
} private class HeartBeatTask implements Runnable{ private final ChannelHandlerContext ctx; public HeartBeatTask(final ChannelHandlerContext ctx) {
this.ctx = ctx;
} @Override
public void run() {
NettyMessage heatBeat = buildHeatBeat();
System.out.println("Client send heart beat message to server:---> "+heatBeat);
ctx.writeAndFlush(heatBeat);
} private NettyMessage buildHeatBeat() {
NettyMessage message = new NettyMessage();
Header header = new Header();
header.setType(MessageType.HEARTBEAT_REQ.value());
message.setHeader(header);
return message;
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if(heartBeat != null){
heartBeat.cancel(true);
heartBeat = null;
}
ctx.fireExceptionCaught(cause);
} }
 package com.cherry.netty.demo.protocolstack.hearthandler;

 import com.cherry.netty.demo.protocolstack.pojo.Header;
import com.cherry.netty.demo.protocolstack.pojo.MessageType;
import com.cherry.netty.demo.protocolstack.pojo.NettyMessage; import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class HeartBeatRespHandler extends ChannelHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
NettyMessage message = (NettyMessage) msg;
if(message.getHeader() != null && message.getHeader().getType()==MessageType.HEARTBEAT_REQ.value()){
System.out.println("Server receive client heart beat message:---> "+message);
NettyMessage heartBeat = buildHeatBeat();
System.out.println("Server send heart beat response message to client:---> "+heartBeat);
ctx.writeAndFlush(heartBeat);
}else{
ctx.fireChannelRead(msg);
}
} private NettyMessage buildHeatBeat() {
NettyMessage message = new NettyMessage();
Header header = new Header();
header.setType(MessageType.HEARTBEAT_RESP.value());
message.setHeader(header);
return message;
} }

5、客户端

 package com.cherry.netty.demo.protocolstack;

 import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import com.cherry.netty.demo.protocolstack.decode.NettyMessageDecoder;
import com.cherry.netty.demo.protocolstack.encode.NettyMessageEncoder;
import com.cherry.netty.demo.protocolstack.hearthandler.HeartBeatReqHandler;
import com.cherry.netty.demo.protocolstack.loginhandler.LoginAuthReqHandler;
import com.cherry.netty.demo.protocolstack.pojo.NettyConstant; 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.timeout.ReadTimeoutHandler; public class NettyClient { private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); public void connect(int port,String host) throws InterruptedException{
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyMessageDecoder(1024*1024, 4, 4));
ch.pipeline().addLast("meaageEncoder",new NettyMessageEncoder());
ch.pipeline().addLast("readTimeoutHandler",new ReadTimeoutHandler(50));
ch.pipeline().addLast("loginAuthHandler",new LoginAuthReqHandler());
ch.pipeline().addLast("heartBeatHandler",new HeartBeatReqHandler()); } });
// 发起异步连接操作
ChannelFuture future = b.connect(
new InetSocketAddress(host, port),
new InetSocketAddress(NettyConstant.LOCALIP, NettyConstant.LOCAL_PORT)).sync();
System.out.println("Netty client start ok . remoteAddress( "+host+":"+port+"),localAddress("+NettyConstant.LOCALIP+":"+NettyConstant.LOCAL_PORT+")"); future.channel().closeFuture().sync(); } finally {
executor.execute(new Runnable() { @Override
public void run() {
try {
TimeUnit.SECONDS.sleep(5);
try {
// 发起重连操作
connect(NettyConstant.REMOTE_PORT, NettyConstant.REMOTEIP);
} catch (Exception e) {
System.out.println("NettyClient 发起重连操作异常");
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
public static void main(String[] args) throws InterruptedException {
new NettyClient().connect(NettyConstant.REMOTE_PORT, NettyConstant.REMOTEIP);
}
}

6、服务端

 package com.cherry.netty.demo.protocolstack;

 import com.cherry.netty.demo.protocolstack.decode.NettyMessageDecoder;
import com.cherry.netty.demo.protocolstack.encode.NettyMessageEncoder;
import com.cherry.netty.demo.protocolstack.hearthandler.HeartBeatRespHandler;
import com.cherry.netty.demo.protocolstack.loginhandler.LoginAuthRespHandler;
import com.cherry.netty.demo.protocolstack.pojo.NettyConstant; 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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler; public class NettyServer { public void bind() throws InterruptedException{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyMessageDecoder(1024*1024, 4, 4));
ch.pipeline().addLast(new NettyMessageEncoder());
ch.pipeline().addLast("readTimeoutHandler",new ReadTimeoutHandler(50));
ch.pipeline().addLast(new LoginAuthRespHandler());
ch.pipeline().addLast("HeartBeatHandler",new HeartBeatRespHandler());
}
}); ChannelFuture future = b.bind(NettyConstant.REMOTEIP,NettyConstant.REMOTE_PORT).sync();
System.out.println("Netty server start ok : "+(NettyConstant.REMOTEIP+":"+NettyConstant.REMOTE_PORT)); future.channel().closeFuture().sync();
}
public static void main(String[] args) throws InterruptedException {
new NettyServer().bind();
} }

Netty私有协议栈 读书笔记的更多相关文章

  1. netty——私有协议栈开发案例

    netty--私有协议栈开发案例 摘要: 在学习李林峰老师的Netty权威指南中,觉得第十二章<私有协议栈开发>中的案例代码比较有代表性,讲的也不错,但是代码中个人认为有些简单的错误,个人 ...

  2. netty 私有协议栈

    通信协议从广义上区分,可以分为公有协议和私有协议.由于私有协议的灵活性,它往往会在某个公司或者组织内部使用,按需定制,也因为如此,升级起来会非常方便,灵活性好.绝大多数的私有协议传输层都基于TCP/I ...

  3. 简易RPC框架-私有协议栈

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  4. 《Netty权威指南》笔记

    第1章 Java的I/O演进之路 1.1 Linux网络I/O模型 fd:file descriptor,文件描述符.linux内核将所有外部设备都看作一个文件来操作,对文件的读写会调用内核提供的命令 ...

  5. 基于Netty的私有协议栈的开发

    基于Netty的私有协议栈的开发 书是人类进步的阶梯,每读一本书都使自己得以提升,以前看书都是看了就看了,当时感觉受益匪浅,时间一长就又还回到书本了!所以说,好记性不如烂笔头,以后每次看完一本书都写一 ...

  6. SSL读书笔记

    摘要: 第一次写博客,为读书笔记,参考书目如下: <HTTP权威指南> <图解HTTP> <大型分布式网站架构设计与实践> 作者:陈康贤 一. HTTP+SSL=H ...

  7. HTTP权威指南读书笔记

    HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...

  8. Spark存储管理(读书笔记)

    Spark存储管理(读书笔记) 转载请注明出处:http://www.cnblogs.com/BYRans/ Spark的存储管理 RDD的存放和管理都是由Spark的存储管理模块实现和管理的.本文从 ...

  9. 《你必须知道的.NET》读书笔记一:小OO有大智慧

    此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.对象  (1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初 ...

随机推荐

  1. linux中readl()和writel()函数---用于读写寄存器

    writel() 往内存映射的 I/O 空间上写数据,wirtel() I/O 上写入 32 位数据 (4字节). 原型: #include <asm/io.h> void writel ...

  2. POJ - 3254 Corn Fields(状压DP)题解

    思路: 参照blog,用状压DP做,和题解稍微有点不一样,我这里直接储存了状态而不是索引. 这一题的问题是怎么判断相邻不能种,我们用2进制来表示每一行的种植情况.我们将每一行所能够造的所有可能都打表( ...

  3. HDU 1166 敌兵布阵(线段树 or 二叉索引树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=50000),表示敌人有 ...

  4. hdu 4739 Zhuge Liang's Mines DFS

    http://acm.hdu.edu.cn/showproblem.php?pid=4739 题意: 给定100*100的矩阵中n(n<= 20)个点,每次只能一走能够形成正方形的四个点,正方形 ...

  5. PHP+MySql+jQuery实现的“顶”和“踩”投票功能

    index.html <!DOCTYPE HTML><html><head><meta charset="utf-8"><ti ...

  6. [原][osgearth]earth文件加载道路一初步看见模型道路

    时间是2017年2月5日17:16:32 由于OE2.9还没有发布,但是我又急于使用OE的道路. 所以,我先编译了正在github上调试中的OE2.9 github网址是:https://github ...

  7. git 沙河游戏节点图, 自由沙盒模拟git, 各类交互git命令

    git学习练习总资源链接: https://try.github.io/ (练习已通,有document) 本沙盒游戏教学:https://learngitbranching.js.org/?demo ...

  8. vsftpd日志配置及查看——可以将vsftpd记录在系统日志里

    vsftpd日志配置及查看 vsftpd ftp服务器的日志设置,可以通过修改主配置文件/etc/vsftpd.conf实现.主配置文件中与日志设置有关的选项包括xferlog_enable .xfe ...

  9. 认识Applet和Ajax

    一.Applet 1.Applet的定义:Applet是采用Java编程语言编写的小应用程序,该程序可以包含在HTML(标准通用标记语言的一个应用)页中,与在页中包含图像的方式大致相同. Java写出 ...

  10. Junit4与junt3并存时产生的问题

    目前的项目里用junit写单元测试,使用的是junit4,由于大部分开发之前使用的都是junit3,对junit4还不是很熟悉,所以出现了junit3和4混合使用的情况,导致发生了一些问题,这里列举一 ...