View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
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   * A Netty 3 TCP Server.
42   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
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      * {@inheritDoc}
139      * @throws  
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             //bindFuture.sync();
157             //Channel channel = bindFuture.channel();
158             //ChannelFuture closeFuture = channel.closeFuture();
159             //closeFuture.sync();
160         } finally {
161         }
162     }
163 
164     /**
165      * {@inheritedDoc}
166      */
167     public void stop() throws IOException {
168         bootstrap.childGroup().shutdownGracefully();
169         bootstrap.group().shutdownGracefully();
170     }
171 }