protobuf
person
package cn.enjoyedu.nettybasic.serializable.protobuf;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:实体类
*/
public class Person {
String name;
int id;
String email;
}
PersonProto
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Person.proto
package cn.enjoyedu.nettybasic.serializable.protobuf;
public final class PersonProto {
private PersonProto() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
}
public interface PersonOrBuilder extends
// @@protoc_insertion_point(interface_extends:netty.Person)
com.google.protobuf.MessageOrBuilder {
/**
* <code>required int32 id = 1;</code>
*/
boolean hasId();
/**
* <code>required int32 id = 1;</code>
*/
int getId();
/**
* <code>required string name = 2;</code>
*/
boolean hasName();
/**
* <code>required string name = 2;</code>
*/
String getName();
/**
* <code>required string name = 2;</code>
*/
com.google.protobuf.ByteString
getNameBytes();
/**
* <code>optional string email = 3;</code>
*/
boolean hasEmail();
/**
* <code>optional string email = 3;</code>
*/
String getEmail();
/**
* <code>optional string email = 3;</code>
*/
com.google.protobuf.ByteString
getEmailBytes();
}
/**
* Protobuf type {@code netty.Person}
*/
public static final class Person extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:netty.Person)
PersonOrBuilder {
// Use Person.newBuilder() to construct.
private Person(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
this.unknownFields = builder.getUnknownFields();
}
private Person(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
private static final Person defaultInstance;
public static Person getDefaultInstance() {
return defaultInstance;
}
public Person getDefaultInstanceForType() {
return defaultInstance;
}
private final com.google.protobuf.UnknownFieldSet unknownFields;
@Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private Person(
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;
}
}
}
} 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 PersonProto.internal_static_netty_Person_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonProto.internal_static_netty_Person_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Person.class, Builder.class);
}
public static com.google.protobuf.Parser<Person> PARSER =
new com.google.protobuf.AbstractParser<Person>() {
public Person parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new Person(input, extensionRegistry);
}
};
@Override
public com.google.protobuf.Parser<Person> getParserForType() {
return PARSER;
}
private int bitField0_;
public static final int ID_FIELD_NUMBER = 1;
private int id_;
/**
* <code>required int32 id = 1;</code>
*/
public boolean hasId() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>required int32 id = 1;</code>
*/
public int getId() {
return id_;
}
public static final int NAME_FIELD_NUMBER = 2;
private Object name_;
/**
* <code>required string name = 2;</code>
*/
public boolean hasName() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>required string name = 2;</code>
*/
public String getName() {
Object ref = name_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
name_ = s;
}
return s;
}
}
/**
* <code>required string name = 2;</code>
*/
public com.google.protobuf.ByteString
getNameBytes() {
Object ref = name_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
name_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int EMAIL_FIELD_NUMBER = 3;
private Object email_;
/**
* <code>optional string email = 3;</code>
*/
public boolean hasEmail() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional string email = 3;</code>
*/
public String getEmail() {
Object ref = email_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
email_ = s;
}
return s;
}
}
/**
* <code>optional string email = 3;</code>
*/
public com.google.protobuf.ByteString
getEmailBytes() {
Object ref = email_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
email_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private void initFields() {
id_ = 0;
name_ = "";
email_ = "";
}
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;
}
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());
}
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());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@Override
protected Object writeReplace()
throws java.io.ObjectStreamException {
return super.writeReplace();
}
public static Person parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Person parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Person parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Person parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Person parseFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static Person parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
public static Person parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input);
}
public static Person parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry);
}
public static Person parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static Person 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(Person prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
@Override
protected Builder newBuilderForType(
BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code netty.Person}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:netty.Person)
PersonOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return PersonProto.internal_static_netty_Person_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonProto.internal_static_netty_Person_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Person.class, Builder.class);
}
// Construct using PersonProto.Person.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
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();
id_ = 0;
bitField0_ = (bitField0_ & ~0x00000001);
name_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
email_ = "";
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
public Builder clone() {
return create().mergeFrom(buildPartial());
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return PersonProto.internal_static_netty_Person_descriptor;
}
public Person getDefaultInstanceForType() {
return Person.getDefaultInstance();
}
public Person build() {
Person result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public Person buildPartial() {
Person result = new Person(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_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof Person) {
return mergeFrom((Person)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(Person other) {
if (other == Person.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();
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
public final boolean isInitialized() {
if (!hasId()) {
return false;
}
if (!hasName()) {
return false;
}
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Person parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (Person) e.getUnfinishedMessage();
throw e;
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private int bitField0_;
private int id_ ;
/**
* <code>required int32 id = 1;</code>
*/
public boolean hasId() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>required int32 id = 1;</code>
*/
public int getId() {
return id_;
}
/**
* <code>required int32 id = 1;</code>
*/
public Builder setId(int value) {
bitField0_ |= 0x00000001;
id_ = value;
onChanged();
return this;
}
/**
* <code>required int32 id = 1;</code>
*/
public Builder clearId() {
bitField0_ = (bitField0_ & ~0x00000001);
id_ = 0;
onChanged();
return this;
}
private Object name_ = "";
/**
* <code>required string name = 2;</code>
*/
public boolean hasName() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>required string name = 2;</code>
*/
public String getName() {
Object ref = name_;
if (!(ref instanceof String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
name_ = s;
}
return s;
} else {
return (String) ref;
}
}
/**
* <code>required string name = 2;</code>
*/
public com.google.protobuf.ByteString
getNameBytes() {
Object ref = name_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
name_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>required string name = 2;</code>
*/
public Builder setName(
String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
name_ = value;
onChanged();
return this;
}
/**
* <code>required string name = 2;</code>
*/
public Builder clearName() {
bitField0_ = (bitField0_ & ~0x00000002);
name_ = getDefaultInstance().getName();
onChanged();
return this;
}
/**
* <code>required string name = 2;</code>
*/
public Builder setNameBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
name_ = value;
onChanged();
return this;
}
private Object email_ = "";
/**
* <code>optional string email = 3;</code>
*/
public boolean hasEmail() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>optional string email = 3;</code>
*/
public String getEmail() {
Object ref = email_;
if (!(ref instanceof String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
email_ = s;
}
return s;
} else {
return (String) ref;
}
}
/**
* <code>optional string email = 3;</code>
*/
public com.google.protobuf.ByteString
getEmailBytes() {
Object ref = email_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
email_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string email = 3;</code>
*/
public Builder setEmail(
String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000004;
email_ = value;
onChanged();
return this;
}
/**
* <code>optional string email = 3;</code>
*/
public Builder clearEmail() {
bitField0_ = (bitField0_ & ~0x00000004);
email_ = getDefaultInstance().getEmail();
onChanged();
return this;
}
/**
* <code>optional string email = 3;</code>
*/
public Builder setEmailBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000004;
email_ = value;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:netty.Person)
}
static {
defaultInstance = new Person(true);
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:netty.Person)
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_netty_Person_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_netty_Person_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
String[] descriptorData = {
"\n\014Person.proto\022\005netty\"1\n\006Person\022\n\n\002id\030\001 " +
"\002(\005\022\014\n\004name\030\002 \002(\t\022\r\n\005email\030\003 \001(\tB:\n+cn.e" +
"njoyedu.ch02.serializable.protobuf.demoB" +
"\013PersonProto"
};
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_Person_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_netty_Person_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_netty_Person_descriptor,
new String[] { "Id", "Name", "Email", });
}
// @@protoc_insertion_point(outer_class_scope)
}
ProtoBufClient
package cn.enjoyedu.nettybasic.serializable.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.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:
*/
public class ProtoBufClient {
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<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
/*加一个消息长度,由netty自动计算*/
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 {
// 优雅退出,释放NIO线程组
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 8080;
new ProtoBufClient().connect(port, "127.0.0.1");
}
}
ProtoBufClientHandler
package cn.enjoyedu.nettybasic.serializable.protobuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:
*/
public class ProtoBufClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("Prepare to make data........");
PersonProto.Person.Builder builder = PersonProto.Person.newBuilder();
builder.setName("Mark");
builder.setId(1);
builder.setEmail("Mark@enjoyedu.com");
System.out.println("send data........");
ctx.writeAndFlush(builder.build());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
ProtoBufServer
package cn.enjoyedu.nettybasic.serializable.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.ProtobufVarint32FrameDecoder;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:
*/
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)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
/*去除消息长度部分,同时根据这个消息长度读取实际的数据*/
ch.pipeline().addLast(
new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(
PersonProto.Person.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;
new ProtoBufServer().bind(port);
}
}
ProtoBufServerHandler
package cn.enjoyedu.nettybasic.serializable.protobuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.io.IOException;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:
*/
public class ProtoBufServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
PersonProto.Person req = (PersonProto.Person)msg;
System.out.println("get data name = "+req.getName());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if(cause instanceof IOException){
System.out.println("远程客户端强迫关闭了一个现有的连接。");
}
ctx.close();
}
}
protogenesis
package-info
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:Java序列化的缺点,从性能、大小上和我们自定义的序列化机制进行比较
*/
package cn.enjoyedu.nettybasic.serializable.protogenesis;
PerformTestUserInfo
/*
* Copyright 2013-2018 Lilinfeng.
*
* 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 cn.enjoyedu.nettybasic.serializable.protogenesis;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:测试序列化性能差异
*/
public class PerformTestUserInfo {
public static void main(String[] args) throws IOException {
UserInfo info = new UserInfo();
info.buildUserID(100).buildUserName("Welcome to Netty");
int loop = 1000000;
ByteArrayOutputStream bos = null;
ObjectOutputStream os = null;
long startTime = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
bos = new ByteArrayOutputStream();
os = new ObjectOutputStream(bos);
os.writeObject(info);
os.flush();
os.close();
byte[] b = bos.toByteArray();
bos.close();
}
long endTime = System.currentTimeMillis();
System.out.println("The jdk serializable cost time is : "
+ (endTime - startTime) + " ms");
System.out.println("-------------------------------------");
ByteBuffer buffer = ByteBuffer.allocate(1024);
startTime = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
byte[] b = info.codeC(buffer);
}
endTime = System.currentTimeMillis();
System.out.println("The byte array serializable cost time is : "
+ (endTime - startTime) + " ms");
}
}
TestUserInfo
/*
* Copyright 2013-2018 Lilinfeng.
*
* 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 cn.enjoyedu.nettybasic.serializable.protogenesis;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:测试序列化后字节大小
*/
public class TestUserInfo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
UserInfo info = new UserInfo();
info.buildUserID(100).buildUserName("Welcome to Netty");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(info);
os.flush();
os.close();
byte[] b = bos.toByteArray();
System.out.println("The jdk serializable length is : " + b.length);
bos.close();
System.out.println("-------------------------------------");
System.out.println("The byte array serializable length is : "
+ info.codeC().length);
}
}
UserInfo
package cn.enjoyedu.nettybasic.serializable.protogenesis;
import java.io.Serializable;
import java.nio.ByteBuffer;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:实体类
*/
public class UserInfo implements Serializable {
/**
* 默认的序列号
*/
private static final long serialVersionUID = 1L;
private String userName;
private int userID;
public UserInfo buildUserName(String userName) {
this.userName = userName;
return this;
}
public UserInfo buildUserID(int userID) {
this.userID = userID;
return this;
}
public final String getUserName() {
return userName;
}
public final void setUserName(String userName) {
this.userName = userName;
}
public final int getUserID() {
return userID;
}
public final void setUserID(int userID) {
this.userID = userID;
}
//自行序列化
public byte[] codeC() {
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte[] value = this.userName.getBytes();//userName转换为字节数组value
buffer.putInt(value.length);//写入字节数组value的长度
buffer.put(value);//写入字节数组value的值
buffer.putInt(this.userID);//写入userID的值
buffer.flip();//准备读取buffer中的数据
value = null;
byte[] result = new byte[buffer.remaining()];
buffer.get(result);//buffer中的数据写入字节数组并作为结果返回
return result;
}
//自行序列化方法2
public byte[] codeC(ByteBuffer buffer) {
buffer.clear();
byte[] value = this.userName.getBytes();
buffer.putInt(value.length);
buffer.put(value);
buffer.putInt(this.userID);
buffer.flip();
value = null;
byte[] result = new byte[buffer.remaining()];
buffer.get(result);
return result;
}
}
msgpack
ClientMsgPackEcho
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
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.LengthFieldPrepender;
import io.netty.handler.codec.LineBasedFrameDecoder;
import java.net.InetSocketAddress;
/**
* 作者:Mark/Maoke
* 创建日期:2018/08/26
* 类说明:
*/
public class ClientMsgPackEcho {
private final String host;
public ClientMsgPackEcho(String host) {
this.host = host;
}
public void start() throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();/*线程组*/
try {
final Bootstrap b = new Bootstrap();;/*客户端启动必须*/
b.group(group)/*将线程组传入*/
.channel(NioSocketChannel.class)/*指定使用NIO进行网络传输*/
/*配置要连接服务器的ip地址和端口*/
.remoteAddress(
new InetSocketAddress(host, ServerMsgPackEcho.PORT))
.handler(new ChannelInitializerImp());
ChannelFuture f = b.connect().sync();
System.out.println("已连接到服务器.....");
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
private static class ChannelInitializerImp extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
/*告诉netty,计算一下报文的长度,然后作为报文头加在前面*/
ch.pipeline().addLast(new LengthFieldPrepender(2));
/*对服务器的应答也要解码,解决粘包半包*/
ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
/*对我们要发送的数据做编码-序列化*/
ch.pipeline().addLast(new MsgPackEncode());
ch.pipeline().addLast(new MsgPackClientHandler(5));
}
}
public static void main(String[] args) throws InterruptedException {
new ClientMsgPackEcho("127.0.0.1").start();
}
}
MsgPackClientHandler
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 作者:Mark/Maoke
* 创建日期:2018/08/26
* 类说明:
*/
public class MsgPackClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final int sendNumber;
public MsgPackClientHandler(int sendNumber) {
this.sendNumber = sendNumber;
}
private AtomicInteger counter = new AtomicInteger(0);
/*** 客户端读取到网络数据后的处理*/
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("client Accept["+msg.toString(CharsetUtil.UTF_8)
+"] and the counter is:"+counter.incrementAndGet());
}
/*** 客户端被通知channel活跃后,做事*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
User[] users = makeUsers();
//发送数据
for(User user:users){
System.out.println("Send user:"+user);
ctx.write(user);
}
ctx.flush();
}
/*** 发生异常后的处理*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
/*生成用户实体类的数组,以供发送*/
private User[] makeUsers(){
User[] users=new User[sendNumber];
User user =null;
for(int i=0;i<sendNumber;i++){
user=new User();
user.setAge(i);
String userName = "ABCDEFG --->"+i;
user.setUserName(userName);
user.setId("No:"+(sendNumber-i));
user.setUserContact(
new UserContact(userName+"@xiangxue.com","133"));
users[i]=user;
}
return users;
}
}
MsgPackDecoder
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.msgpack.MessagePack;
import java.util.List;
/*基于MessagePack的解码器,反序列化*/
public class MsgPackDecoder extends MessageToMessageDecoder<ByteBuf> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
throws Exception {
final int length = msg.readableBytes();
final byte[] array = new byte[length];
msg.getBytes(msg.readerIndex(),array,0,length);
MessagePack messagePack = new MessagePack();
out.add(messagePack.read(array,User.class));
}
}
MsgPackEncode
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.msgpack.MessagePack;
/*基于MessagePack的编码器,序列化*/
public class MsgPackEncode extends MessageToByteEncoder<User> {
@Override
protected void encode(ChannelHandlerContext ctx, User msg, ByteBuf out)
throws Exception {
MessagePack messagePack = new MessagePack();
byte[] raw = messagePack.write(msg);
out.writeBytes(raw);
}
}
MsgPackServerHandler
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 作者:Mark/Maoke
* 创建日期:2018/08/25
* 类说明:自己的业务处理
*/
@ChannelHandler.Sharable
public class MsgPackServerHandler extends ChannelInboundHandlerAdapter {
private AtomicInteger counter = new AtomicInteger(0);
/*** 服务端读取到网络数据后的处理*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将上一个handler生成的数据强制转型
User user = (User)msg;
System.out.println("Server Accept["+user
+"] and the counter is:"+counter.incrementAndGet());
//服务器的应答
String resp = "I process user :"+user.getUserName()
+ System.getProperty("line.separator");
ctx.writeAndFlush(Unpooled.copiedBuffer(resp.getBytes()));
ctx.fireChannelRead(user);
}
/*** 发生异常后的处理*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
package-info
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 往期课程和VIP课程咨询 依娜老师 QQ:2133576719
* 类说明:本包中的代码演示了:
* 1、LengthFieldBasedFrame的使用
* 2、如何和第三方序列化工具,比如MessagePack进行集成
* 3、如何实现自己的编解码框架
*/
package cn.enjoyedu.nettybasic.serializable.msgpack;
ServerMsgPackEcho
package cn.enjoyedu.nettybasic.serializable.msgpack;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import java.net.InetSocketAddress;
/**
* 作者:Mark/Maoke
* 创建日期:2018/08/25
* 类说明:
*/
public class ServerMsgPackEcho {
public static final int PORT = 9995;
public static void main(String[] args) throws InterruptedException {
ServerMsgPackEcho serverMsgPackEcho = new ServerMsgPackEcho();
System.out.println("服务器即将启动");
serverMsgPackEcho.start();
}
public void start() throws InterruptedException {
final MsgPackServerHandler serverHandler = new MsgPackServerHandler();
EventLoopGroup group = new NioEventLoopGroup();/*线程组*/
try {
ServerBootstrap b = new ServerBootstrap();/*服务端启动必须*/
b.group(group)/*将线程组传入*/
.channel(NioServerSocketChannel.class)/*指定使用NIO进行网络传输*/
.localAddress(new InetSocketAddress(PORT))/*指定服务器监听端口*/
/*服务端每接收到一个连接请求,就会新启一个socket通信,也就是channel,
所以下面这段代码的作用就是为这个子channel增加handle*/
.childHandler(new ChannelInitializerImp());
ChannelFuture f = b.bind().sync();/*异步绑定到服务器,sync()会阻塞直到完成*/
System.out.println("服务器启动完成,等待客户端的连接和数据.....");
f.channel().closeFuture().sync();/*阻塞直到服务器的channel关闭*/
} finally {
group.shutdownGracefully().sync();/*优雅关闭线程组*/
}
}
private static class ChannelInitializerImp extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535,
0,2,0,
2));
ch.pipeline().addLast(new MsgPackDecoder());
ch.pipeline().addLast(new MsgPackServerHandler());
}
}
}
User
package cn.enjoyedu.nettybasic.serializable.msgpack;
import org.msgpack.annotation.Message;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 类说明:实体类
*/
@Message
public class User {
private String id;
private String userName;
private int age;
private UserContact userContact;
public User(String userName, int age, String id) {
this.userName = userName;
this.age = age;
this.id = id;
}
public User() {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public UserContact getUserContact() {
return userContact;
}
public void setUserContact(UserContact userContact) {
this.userContact = userContact;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
", id='" + id + '\'' +
", userContact=" + userContact +
'}';
}
}
UserContact`
package cn.enjoyedu.nettybasic.serializable.msgpack;
import org.msgpack.annotation.Message;
/**
* @author Mark老师 享学课堂 https://enjoy.ke.qq.com
* 类说明:实体类
*/
@Message//MessagePack提供的注解,表明这是一个需要序列化的实体类
public class UserContact {
private String mail;
private String phone;
public UserContact() {
}
public UserContact(String mail, String phone) {
this.mail = mail;
this.phone = phone;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "UserContact{" +
"mail='" + mail + '\'' +
", phone='" + phone + '\'' +
'}';
}
}