Netty私有协议栈 读书笔记
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私有协议栈 读书笔记的更多相关文章
- netty——私有协议栈开发案例
netty--私有协议栈开发案例 摘要: 在学习李林峰老师的Netty权威指南中,觉得第十二章<私有协议栈开发>中的案例代码比较有代表性,讲的也不错,但是代码中个人认为有些简单的错误,个人 ...
- netty 私有协议栈
通信协议从广义上区分,可以分为公有协议和私有协议.由于私有协议的灵活性,它往往会在某个公司或者组织内部使用,按需定制,也因为如此,升级起来会非常方便,灵活性好.绝大多数的私有协议传输层都基于TCP/I ...
- 简易RPC框架-私有协议栈
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 《Netty权威指南》笔记
第1章 Java的I/O演进之路 1.1 Linux网络I/O模型 fd:file descriptor,文件描述符.linux内核将所有外部设备都看作一个文件来操作,对文件的读写会调用内核提供的命令 ...
- 基于Netty的私有协议栈的开发
基于Netty的私有协议栈的开发 书是人类进步的阶梯,每读一本书都使自己得以提升,以前看书都是看了就看了,当时感觉受益匪浅,时间一长就又还回到书本了!所以说,好记性不如烂笔头,以后每次看完一本书都写一 ...
- SSL读书笔记
摘要: 第一次写博客,为读书笔记,参考书目如下: <HTTP权威指南> <图解HTTP> <大型分布式网站架构设计与实践> 作者:陈康贤 一. HTTP+SSL=H ...
- HTTP权威指南读书笔记
HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...
- Spark存储管理(读书笔记)
Spark存储管理(读书笔记) 转载请注明出处:http://www.cnblogs.com/BYRans/ Spark的存储管理 RDD的存放和管理都是由Spark的存储管理模块实现和管理的.本文从 ...
- 《你必须知道的.NET》读书笔记一:小OO有大智慧
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.对象 (1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初 ...
随机推荐
- Java序列化(Serialization)
关于Java的序列化的文章在网上已经够多了,在这里写关于Java序列化的文章是对自己关于这方面的的一种总结,结合以前的开发经验与网上的资料,写了这篇文章,对自己是有着巩固记忆的作用,也希望能够对大家有 ...
- Think in Java笔记——Java与对象
最近在重新学习Java,在阅读Java的经典著作——Java编程思想,因此每天记录阅读的心得. 当听到Java这个词时,大家一般想到的是面向对象,确实Java相对于C/C++这两门语言来说,Java最 ...
- NSwag给api加上说明
参考http://petstore.swagger.io 给controller加上description https://github.com/RSuter/NSwag/issues/1803 xm ...
- exception disappear when forgot to await an async method
https://github.com/aspnet/AspNetWebStack/issues/235 https://stackoverflow.com/questions/5383310/catc ...
- Anaconda ubuntu16.04 Cuda 8.0安装pytorch
Pytorch 安装 Pytorch安装真的太让人省心了,在anaconda的环境下进行安装,只需要一个命令 具体命令请查看官网pytorch 找到适合你的版本进行安装 本机环境: anaconda3 ...
- 深入浅出 Hadoop YARN
一. Hadoop Yarn 是什么 在古老的 Hadoop1.0 中,MapReduce 的 JobTracker 负责了太多的工作,包括资源调度,管理众多的 TaskTracker 等工作.这自然 ...
- How to Restore “TrustedInstaller” as Default Owner of a File
type NT SERVICE\TrustedInstaller in "Enter the object name to select" text box http://www. ...
- Java 调用PHP的Web Service(三)
usoap是PHP环境中的开源soap工具,算是用得比较多的一个工具了. 在utf-8环境中,nusoap可以工作得很好.但是当用于中文环境中时,nusoap经常会出现一些让人不得其解的问题. 最近一 ...
- 002——php字符串中的处理函数(一)
<?php /** * 字符串处理函数: * 一.PHP处理字符串的空格: * strlen 显示字符串长度 * * trim 对字符串左右空格删除: * ltrim 对字符串左侧空格删除 * ...
- FireFox和IE下使用Date来构造新Date对象的BUG
正常方式 我们都知道可以使用new Date()来创建一个Date对象. new Date();//Date {Mon Jun 15 2015 15:53:16 GMT+0800} 也可以用new D ...