protobuf:用于制定数据传输格式,提高数据传输效率。
netty用于javaCS端进行通讯。
一、生成 proto 文件。使用maven插件生成。先取消注释,使用完要注释。(防止maven install错误)
proto文件例子:proto/test.proto
syntax = "proto3";
option java_package = "com.zihai.proto.entity";
option java_outer_classname = "People";
package peple;
message Son{
string name = 1;
int32 age =2;
}
message Parent{
string name = 1;
int32 age = 2;
string like = 3;
}
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<!-- <build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId><!–引入操作系统os设置的属性插件,否则${os.detected.classifier} 操作系统版本会找不到 –>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<!–添加编译proto文件的编译程序和对应的编译插件–>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.14.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>-->
java Client端测试例子
import com.google.gson.Gson;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.zihai.proto.entity.People;
import com.zihai.proto.entity.People.Parent;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import java.util.HashMap;
import java.util.Map;
public class ProtoTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ProtoTest.class);
private static String host = "localhost";
private static int port = 8080;
private static ChannelHandlerContext ctx2 = null;
public static void main(String[] args) throws InvalidProtocolBufferException {
Map<String,Object> data = new HashMap<>();
data.put("name","龙且");
data.put("age",12);
data.put("like","独行");
String obj = new Gson().toJson(data);
Parent.Builder builder = Parent.newBuilder();
JsonFormat.parser().merge(obj, builder);
Parent parent = builder.build();
LOGGER.info( JsonFormat.printer().print(parent));
byte[] bytes = parent.toByteArray();
Parent part = Parent.parseFrom(bytes);
System.out.println(part.getName());
Thread thread = new Thread(){
@Override
public void run() {
try {
Thread.sleep(4000);
Assert.notNull(ctx2,"ctx2 is null");
ctx2.writeAndFlush(part);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap(); // (1)
b.group(workerGroup); // (2)
b.channel(NioSocketChannel.class); // (3)
b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(People.Son.getDefaultInstance()));
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
ch.pipeline().addLast(new TestClientHandler(){
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
LOGGER.info("socket is activity");
ctx2 = ctx;
//ctx.writeAndFlush(part);
/*ByteBuf encoded = ctx.alloc().buffer(bytes.length);
encoded.writeBytes(bytes);
ctx.writeAndFlush(encoded);*/
}
});
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (5)
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
}
}
}
import com.zihai.proto.entity.People;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
@ChannelHandler.Sharable
public class TestClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
People.Son s = (People.Son) msg; // (1)
System.out.println(s.getName());
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("read Complete");
ctx.fireChannelReadComplete();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("有个连接上来了....");
ctx.fireChannelActive();
}
}
java Server端例子
package com.zihai.netty.server;
import com.zihai.proto.entity.People;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
public class TestServer {
private int port;
public TestServer(int port) {
this.port = port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(5); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup(10);
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
System.out.println("server start");
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(People.Parent.getDefaultInstance()));
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
ch.pipeline().addLast(new TestServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (7)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 8080;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
}
new TestServer(port).run();
}
}
package com.zihai.netty.server;
import com.zihai.proto.entity.People;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
@ChannelHandler.Sharable
public class TestServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
System.out.println("channelRead");
try {
People.Parent p= (People.Parent)msg;
People.Son.Builder s = People.Son.newBuilder();
s.setAge(p.getAge());
s.setName(p.getName());
s.build();
ctx.writeAndFlush(s);
/* ByteBuf buf = (ByteBuf) msg;
byte[] array = new byte[buf.readableBytes()];
buf.readBytes(array);
People.Parent part = People.Parent.parseFrom(array);
int length = part.getName().getBytes().length;
ByteBuf encoded = ctx.alloc().buffer(length);
encoded.writeBytes(part.getName().getBytes());
ctx.writeAndFlush(encoded);*/
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("read Complete");
ctx.fireChannelReadComplete();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("有个连接上来了....");
ctx.fireChannelActive();
}
}
公共依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.7.1</version>
</dependency>