Netty 基于Http协议下的数据传输示例
您的评价: |
|
Http/Https协议是最重要最常用到的协议之一,Netty提供了一些了的Handler来处理Http协议下的编码工作。下面就介绍一个Netty实例:
1.通过HttpClient发送Protobuf类型数据到服务端
2.服务端Netty负责把接收到的Http请求中的数据再发送到客户端。
3.其中Netty对发送的数据量没有限制,因为Http发送的message往往是由一系列infragment构成,Netty可以把接收到的http请求片段信息整合(Aggregator)到一起,最终得到一个FullHttpRequest。
Client端:
服务器端NettyService:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package
NettyDemo.echo.server;
import
io.netty.bootstrap.ServerBootstrap;
import
io.netty.channel.ChannelInitializer;
import
io.netty.channel.ChannelPipeline;
import
io.netty.channel.EventLoopGroup;
import
io.netty.channel.nio.NioEventLoopGroup;
import
io.netty.channel.socket.SocketChannel;
import
io.netty.channel.socket.nio.NioServerSocketChannel;
import
io.netty.handler.codec.http.HttpObjectAggregator;
import
io.netty.handler.codec.http.HttpRequestDecoder;
import
io.netty.handler.codec.http.HttpResponseEncoder;
import
io.netty.handler.codec.http.HttpServerCodec;
import
NettyDemo.echo.handler.HttpProtobufServerHandler;
public
class
HttpProtobufServer {
public
static
final
String IP =
"127.0.0.1"
;
public
static
final
int
PORT =
8080
;
//private static MessageLite lite=AddressBookProtos.AddressBook.getDefaultInstance();
/**用于分配处理业务线程的线程组个数 */
protected
static
final
int
BIZGROUPSIZE = Runtime.getRuntime().availableProcessors()*
2
;
//默认
/** 业务出现线程大小*/
protected
static
final
int
BIZTHREADSIZE =
4
;
private
static
final
EventLoopGroup bossGroup =
new
NioEventLoopGroup(BIZGROUPSIZE);
private
static
final
EventLoopGroup workerGroup =
new
NioEventLoopGroup(BIZTHREADSIZE);
protected
static
void
run()
throws
Exception {
ServerBootstrap b =
new
ServerBootstrap();
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.
class
);
b.childHandler(
new
ChannelInitializer<SocketChannel>() {
@Override
public
void
initChannel(SocketChannel ch)
throws
Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(
"decoder"
,
new
HttpRequestDecoder());
/**usually we receive http message infragment,if we want full http message,
* we should bundle HttpObjectAggregator and we can get FullHttpRequest。
* 我们通常接收到的是一个http片段,如果要想完整接受一次请求的所有数据,我们需要绑定HttpObjectAggregator,然后我们
* 就可以收到一个FullHttpRequest-是一个完整的请求信息。
**/
pipeline.addLast(
"servercodec"
,
new
HttpServerCodec());
pipeline.addLast(
"aggegator"
,
new
HttpObjectAggregator(
1024
*
1024
*
64
));
//定义缓冲数据量
pipeline.addLast(
new
HttpProtobufServerHandler());
pipeline.addLast(
"responseencoder"
,
new
HttpResponseEncoder());
}
});
b.bind(IP, PORT).sync();
System.out.println(
"TCP服务器已启动"
);
}
protected
static
void
shutdown() {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
public
static
void
main(String[] args)
throws
Exception {
System.out.println(
"开始启动http服务器..."
);
HttpProtobufServer.run();
// TcpServer.shutdown();
}
}
|
Handler:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package
NettyDemo.echo.handler;
import
io.netty.channel.ChannelHandlerContext;
import
io.netty.channel.SimpleChannelInboundHandler;
import
io.netty.handler.codec.http.DefaultFullHttpRequest;
import
io.netty.handler.codec.http.DefaultFullHttpResponse;
import
io.netty.handler.codec.http.HttpResponseStatus;
import
io.netty.handler.codec.http.HttpVersion;
public
class
HttpProtobufServerHandler
extends
SimpleChannelInboundHandler<Object>{
@Override
protected
void
channelRead0(ChannelHandlerContext ctx, Object msg)
throws
Exception {
DefaultFullHttpRequest request=(DefaultFullHttpRequest)msg;
DefaultFullHttpResponse response=
new
DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.ACCEPTED, request.content());
ctx.writeAndFlush(response);
}
}
|