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 }