1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.nio.tcp;
21
22 import io.netty.bootstrap.ServerBootstrap;
23 import io.netty.buffer.ByteBuf;
24 import io.netty.buffer.Unpooled;
25 import io.netty.channel.ChannelFuture;
26 import io.netty.channel.ChannelHandlerContext;
27 import io.netty.channel.ChannelInboundHandlerAdapter;
28 import io.netty.channel.ChannelInitializer;
29 import io.netty.channel.ChannelOption;
30 import io.netty.channel.nio.NioEventLoopGroup;
31 import io.netty.channel.socket.SocketChannel;
32 import io.netty.channel.socket.nio.NioServerSocketChannel;
33 import io.netty.util.Attribute;
34 import io.netty.util.AttributeKey;
35
36 import java.io.IOException;
37
38 import org.apache.mina.core.BenchmarkServer;
39
40
41
42
43
44 public class Netty4TcpBenchmarkServer implements BenchmarkServer {
45
46 private static enum State {
47 WAIT_FOR_FIRST_BYTE_LENGTH, WAIT_FOR_SECOND_BYTE_LENGTH, WAIT_FOR_THIRD_BYTE_LENGTH, WAIT_FOR_FOURTH_BYTE_LENGTH, READING
48 }
49
50 private static final ByteBuf ACK = Unpooled.buffer(1);
51
52 static {
53 ACK.writeByte(0);
54 }
55
56 private static final AttributeKey<State> STATE_ATTRIBUTE = new AttributeKey<State>("state");
57
58 private static final AttributeKey<Integer> LENGTH_ATTRIBUTE = new AttributeKey<Integer>("length");
59
60 private ServerBootstrap bootstrap = null;
61
62 private class TestServerHandler extends ChannelInboundHandlerAdapter {
63 public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
64 System.out.println("childChannelOpen");
65 ctx.attr(STATE_ATTRIBUTE).set(State.WAIT_FOR_FIRST_BYTE_LENGTH);
66 }
67
68 @Override
69 public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
70 }
71
72 @Override
73 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
74 cause.printStackTrace();
75 }
76
77 @Override
78 public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
79 ByteBuf buffer = (ByteBuf)message;
80 State state = ctx.attr(STATE_ATTRIBUTE).get();
81 int length = 0;
82 Attribute<Integer> lengthAttribute = ctx.attr(LENGTH_ATTRIBUTE);
83
84 if (lengthAttribute.get() != null) {
85 length = lengthAttribute.get();
86 }
87
88 while (buffer.readableBytes() > 0) {
89 switch (state) {
90 case WAIT_FOR_FIRST_BYTE_LENGTH:
91 length = (buffer.readByte() & 255) << 24;
92 state = State.WAIT_FOR_SECOND_BYTE_LENGTH;
93 break;
94
95 case WAIT_FOR_SECOND_BYTE_LENGTH:
96 length += (buffer.readByte() & 255) << 16;
97 state = State.WAIT_FOR_THIRD_BYTE_LENGTH;
98 break;
99
100 case WAIT_FOR_THIRD_BYTE_LENGTH:
101 length += (buffer.readByte() & 255) << 8;
102 state = State.WAIT_FOR_FOURTH_BYTE_LENGTH;
103 break;
104
105 case WAIT_FOR_FOURTH_BYTE_LENGTH:
106 length += (buffer.readByte() & 255);
107 state = State.READING;
108
109 if ((length == 0) && (buffer.readableBytes() == 0)) {
110 ctx.writeAndFlush(ACK.retain(1).resetReaderIndex());
111 state = State.WAIT_FOR_FIRST_BYTE_LENGTH;
112 }
113
114 break;
115
116 case READING:
117 int remaining = buffer.readableBytes();
118
119 if (length > remaining) {
120 length -= remaining;
121 buffer.skipBytes(remaining);
122 } else {
123 buffer.skipBytes(length);
124 ctx.writeAndFlush(ACK.retain(1).resetReaderIndex());
125 state = State.WAIT_FOR_FIRST_BYTE_LENGTH;
126 length = 0;
127 }
128 }
129 }
130
131 ctx.attr(STATE_ATTRIBUTE).set(state);
132 ctx.attr(LENGTH_ATTRIBUTE).set(length);
133 buffer.release();
134 }
135 }
136
137
138
139
140
141 public void start(int port) throws IOException {
142 try {
143 bootstrap = new ServerBootstrap();
144 bootstrap.option(ChannelOption.SO_RCVBUF, 128 * 1024);
145 bootstrap.option(ChannelOption.TCP_NODELAY, true);
146 bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup());
147 bootstrap.channel(NioServerSocketChannel.class);
148 bootstrap.localAddress(port);
149 bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
150 @Override
151 public void initChannel(SocketChannel channel) throws Exception {
152 channel.pipeline().addLast(new TestServerHandler());
153 };
154 });
155 ChannelFuture bindFuture = bootstrap.bind();
156
157
158
159
160 } finally {
161 }
162 }
163
164
165
166
167 public void stop() throws IOException {
168 bootstrap.childGroup().shutdownGracefully();
169 bootstrap.group().shutdownGracefully();
170 }
171 }